diff --git a/README.markdown b/README.markdown
index d9594c0f..daf6d753 100644
--- a/README.markdown
+++ b/README.markdown
@@ -136,9 +136,12 @@ NVTOP includes some initial support for Apple using Metal. This is only supporte
### Ascend
-NVTOP supports Ascend (testing on Altas 800 (910B)) by DCMI API (version 6.0.0).
-
-Currently, the DCMI only supports limited APIs, missing PCIe generation, tx/rx throughput info, max power draw etc.
+NVTOP supports Ascend through the DCMI API (tested on 910B3 hardware). It
+uses the logical-device API when available and falls back to the legacy
+card/device API. Read-only telemetry is reported when supported by the
+installed driver; unavailable values remain unset. Enable it with
+`-DASCEND_SUPPORT=ON`, and set `-DASCEND_ROOT=/path/to/Ascend` when CANN is
+installed outside the standard locations.
### Iluvatar CoreX
diff --git a/include/ascend/dcmi_interface_api.h b/include/ascend/dcmi_interface_api.h
index 3217c587..410d0c85 100644
--- a/include/ascend/dcmi_interface_api.h
+++ b/include/ascend/dcmi_interface_api.h
@@ -27,10 +27,34 @@ extern "C" {
#define DCMIDLLEXPORT _declspec(dllexport)
#endif
+/* Newer DCMI entry points are optional so older Ascend drivers remain usable. */
+#if defined(__GNUC__)
+#define DCMI_WEAK __attribute__((weak))
+#else
+#define DCMI_WEAK
+#endif
+
#define MAX_CARD_NUM 64
#define MAX_CHIP_NAME_LEN 32 // Maximum length of chip name
+#define MAX_VERSION_LEN 255
+#define MAX_LENTH 256
+#define MAX_CORE_NUM 16
+#define DCMI_CPU_NUM_CFG_LEN 16
#define TEMPLATE_NAME_LEN 32
#define DIE_ID_COUNT 5 // Number of die ID characters
+#define DCMI_HCCS_MAX_PCS_NUM 16
+#define DCMI_UB_PORT_NUM 36
+#define MAX_DIE_NUMS 2
+#define MAX_PORT_NUMS 32
+#define NETDEV_MAX_NUM 8
+#define NETDEV_NAME_MAX_LEN 16
+#define TC_MAX_NUM 8
+#define DCMI_PORT_PKT_STATS_NUM 48
+#define MAX_RECORD_ECC_ADDR_COUNT 64
+#define UB_MODE 0
+#define UBOE_MODE 1
+
+struct dsmi_computing_power_info;
#define DCMI_UTILIZATION_RATE_DDR 1
#define DCMI_UTILIZATION_RATE_AICORE 2
@@ -40,16 +64,36 @@ extern "C" {
#define DCMI_UTILIZATION_RATE_HBM 6
#define DCMI_UTILIZATION_RATE_HBM_BANDWIDTH 10
#define DCMI_UTILIZATION_RATE_VECTORCORE 12
-
- /*----------------------------------------------*
-* Structure description *
-*----------------------------------------------*/
- struct dcmi_chip_info {
- unsigned char chip_type[MAX_CHIP_NAME_LEN];
- unsigned char chip_name[MAX_CHIP_NAME_LEN];
- unsigned char chip_ver[MAX_CHIP_NAME_LEN];
- unsigned int aicore_cnt;
- };
+#define DCMI_UTILIZATION_RATE_NPU 13
+#define DCMI_UTILIZATION_RATE_AICUBE 14
+
+/*----------------------------------------------*
+ * Structure description *
+ *----------------------------------------------*/
+struct dcmi_chip_info {
+ unsigned char chip_type[MAX_CHIP_NAME_LEN];
+ unsigned char chip_name[MAX_CHIP_NAME_LEN];
+ unsigned char chip_ver[MAX_CHIP_NAME_LEN];
+ unsigned int aicore_cnt;
+};
+
+struct dcmi_chip_info_v2 {
+ unsigned char chip_type[MAX_CHIP_NAME_LEN];
+ unsigned char chip_name[MAX_CHIP_NAME_LEN];
+ unsigned char chip_ver[MAX_CHIP_NAME_LEN];
+ unsigned int aicore_cnt;
+ unsigned char npu_name[MAX_CHIP_NAME_LEN];
+};
+
+struct dcmi_pcie_info {
+ unsigned int deviceid;
+ unsigned int venderid;
+ unsigned int subvenderid;
+ unsigned int subdeviceid;
+ unsigned int bdf_deviceid;
+ unsigned int bdf_busid;
+ unsigned int bdf_funcid;
+};
struct dcmi_pcie_info_all {
unsigned int venderid;
@@ -63,10 +107,140 @@ extern "C" {
unsigned char reserve[32]; /* the size of dcmi_pcie_info_all is 64 */
};
+ struct dcmi_ub_id_info {
+ unsigned short device_id;
+ unsigned short vendor_id;
+ unsigned short module_vendor_id;
+ unsigned short module_id;
+ unsigned char reserved[32];
+ };
+
struct dcmi_die_id {
unsigned int soc_die[DIE_ID_COUNT];
};
+ struct dcmi_aicore_info {
+ unsigned int freq;
+ unsigned int cur_freq;
+ };
+
+ struct dcmi_aicpu_info {
+ unsigned int max_freq;
+ unsigned int cur_freq;
+ unsigned int aicpu_num;
+ unsigned int util_rate[MAX_CORE_NUM];
+ };
+
+ /* V1 compatibility structures used by the legacy alias entry points. The
+ * fields intentionally keep the names from the CANN ABI; their layout is
+ * identical to the dcmi_* structures above. */
+ struct dsmi_aicore_info_stru {
+ unsigned int freq;
+ unsigned int curfreq;
+ };
+
+ struct dsmi_aicpu_info_stru {
+ unsigned int maxFreq;
+ unsigned int curFreq;
+ unsigned int aicpuNum;
+ unsigned int utilRate[MAX_CORE_NUM];
+ };
+
+ struct dcmi_multi_utilization_info {
+ unsigned int aic_util;
+ unsigned int aiv_util;
+ unsigned int aicore_util;
+ unsigned int npu_util;
+ unsigned int reserved[8];
+ };
+
+ enum dcmi_device_type {
+ DCMI_DEVICE_TYPE_DDR = 0,
+ DCMI_DEVICE_TYPE_SRAM,
+ DCMI_DEVICE_TYPE_HBM,
+ DCMI_DEVICE_TYPE_NPU,
+ DCMI_HBM_RECORDED_SINGLE_ADDR,
+ DCMI_HBM_RECORDED_MULTI_ADDR,
+ DCMI_DEVICE_TYPE_NONE = 0xff
+ };
+
+ struct dcmi_ecc_info {
+ int enable_flag;
+ unsigned int single_bit_error_cnt;
+ unsigned int double_bit_error_cnt;
+ unsigned int total_single_bit_error_cnt;
+ unsigned int total_double_bit_error_cnt;
+ unsigned int single_bit_isolated_pages_cnt;
+ unsigned int double_bit_isolated_pages_cnt;
+ };
+
+ struct dcmi_chip_pcie_err_rate {
+ unsigned int reg_deskew_fifo_overflow_intr_status;
+ unsigned int reg_symbol_unlock_intr_status;
+ unsigned int reg_deskew_unlock_intr_status;
+ unsigned int reg_phystatus_timeout_intr_status;
+ unsigned int symbol_unlock_counter;
+ unsigned int pcs_rx_err_cnt;
+ unsigned int phy_lane_err_counter;
+ unsigned int pcs_rcv_err_status;
+ unsigned int symbol_unlock_err_status;
+ unsigned int phy_lane_err_status;
+ unsigned int dl_lcrc_err_num;
+ unsigned int dl_dcrc_err_num;
+ };
+
+ struct dcmi_pcie_link_error_info {
+ unsigned int tx_err_cnt;
+ unsigned int rx_err_cnt;
+ unsigned int lcrc_err_cnt;
+ unsigned int ecrc_err_cnt;
+ unsigned int retry_cnt;
+ unsigned int rsv[32];
+ };
+
+ enum dcmi_manager_sensor_id {
+ DCMI_CLUSTER_TEMP_ID = 0,
+ DCMI_PERI_TEMP_ID = 1,
+ DCMI_AICORE0_TEMP_ID,
+ DCMI_AICORE1_TEMP_ID,
+ DCMI_AICORE_LIMIT_ID,
+ DCMI_AICORE_TOTAL_PER_ID,
+ DCMI_AICORE_ELIM_PER_ID,
+ DCMI_AICORE_BASE_FREQ_ID,
+ DCMI_NPU_DDR_FREQ_ID,
+ DCMI_THERMAL_THRESHOLD_ID,
+ DCMI_NTC_TEMP_ID,
+ DCMI_SOC_TEMP_ID,
+ DCMI_FP_TEMP_ID,
+ DCMI_N_DIE_TEMP_ID,
+ DCMI_HBM_TEMP_ID,
+ DCMI_SENSOR_INVALID_ID = 255
+ };
+
+ union dcmi_sensor_info {
+ unsigned char uchar;
+ unsigned short ushort;
+ unsigned int uint;
+ signed int iint;
+ signed char temp[2];
+ signed int ntc_tmp[4];
+ unsigned int data[16];
+ };
+
+ struct dcmi_memory_info {
+ unsigned long long memory_size; /* unit:MB */
+ unsigned int freq; /* unit:MHz */
+ unsigned int utiliza; /* unit:% */
+ };
+
+ struct dcmi_dvpp_ratio {
+ int vdec_ratio;
+ int vpc_ratio;
+ int venc_ratio;
+ int jpege_ratio;
+ int jpegd_ratio;
+ };
+
struct dcmi_hbm_info {
unsigned long long memory_size;
unsigned int freq;
@@ -75,6 +249,65 @@ extern "C" {
unsigned int bandwith_util_rate;
};
+ struct dcmi_hbm_product_info {
+ unsigned short manufacturer_id;
+ unsigned char reserve[62];
+ };
+
+ struct dcmi_flash_info {
+ unsigned long long flash_id;
+ unsigned short device_id;
+ unsigned short vendor;
+ unsigned int state;
+ unsigned long long size;
+ unsigned int sector_count;
+ unsigned short manufacturer_id;
+ };
+
+ /* The legacy symbol uses a separately named structure in the CANN ABI.
+ * Keep the tag distinct so calls are type-checked against the public
+ * declaration; both layouts are intentionally identical. */
+ struct dcmi_flash_info_stru {
+ unsigned long long flash_id;
+ unsigned short device_id;
+ unsigned short vendor;
+ unsigned int state;
+ unsigned long long size;
+ unsigned int sector_count;
+ unsigned short manufacturer_id;
+ };
+
+ /* ECC history records are part of the current CANN ABI. They are kept
+ * separate from dcmi_ecc_info because the latter is a counter snapshot. */
+ enum ECC_INFO_READ {
+ MULTI_ECC_TIMES_READ = 0,
+ SINGLE_ECC_INFO_READ,
+ MULTI_ECC_INFO_READ,
+ ECC_ADDRESS_COUNT_READ,
+ ECC_MAX_READ_CMD
+ };
+
+ struct dcmi_ecc_record_type {
+ enum ECC_INFO_READ read_type;
+ enum dcmi_device_type module_type;
+ };
+
+#pragma pack(push, 1)
+ struct dcmi_multi_ecc_time_data {
+ unsigned int multi_record_count;
+ unsigned int multi_ecc_times[MAX_RECORD_ECC_ADDR_COUNT];
+ };
+
+ struct dcmi_ecc_common_data {
+ unsigned long long physical_addr;
+ unsigned int stack_pc_id;
+ unsigned int reg_addr_h;
+ unsigned int reg_addr_l;
+ unsigned int ecc_count;
+ int timestamp;
+ };
+#pragma pack(pop)
+
struct dcmi_get_memory_info_stru {
unsigned long long memory_size; /* unit:MB */
unsigned long long memory_available; /* free + hugepages_free * hugepagesize */
@@ -82,7 +315,7 @@ extern "C" {
unsigned long hugepagesize; /* unit:KB */
unsigned long hugepages_total;
unsigned long hugepages_free;
- unsigned int utilize; /* ddr memory info usages */
+ unsigned int utiliza; /* ddr memory info usages */
unsigned char reserve[60]; /* the size of dcmi_memory_info is 96 */
};
@@ -120,6 +353,8 @@ extern "C" {
DCMI_RDFX_DETECT_MAX = 0xFF
};
+ enum dcmi_device_compat { DCMI_COMPAT_OK = 1, DCMI_COMPAT_NOK = 2, DCMI_COMPAT_UNKNOWN = 3 };
+
enum dcmi_port_type {
DCMI_VNIC_PORT = 0,
DCMI_ROCE_PORT = 1,
@@ -133,10 +368,27 @@ extern "C" {
DCMI_MAIN_CMD_CAN,
DCMI_MAIN_CMD_UART,
DCMI_MAIN_CMD_UPGRADE,
+ DCMI_MAIN_CMD_UFS,
+ DCMI_MAIN_CMD_OS_POWER,
+ DCMI_MAIN_CMD_LP,
+ DCMI_MAIN_CMD_MEMORY,
+ DCMI_MAIN_CMD_RECOVERY,
+ DCMI_MAIN_CMD_TS,
+ DCMI_MAIN_CMD_CHIP_INF,
+ DCMI_MAIN_CMD_QOS,
+ DCMI_MAIN_CMD_SOC_INFO,
+ DCMI_MAIN_CMD_SILS,
+ DCMI_MAIN_CMD_HCCS,
+ DCMI_MAIN_CMD_HOST_AICPU,
DCMI_MAIN_CMD_TEMP = 50,
DCMI_MAIN_CMD_SVM = 51,
DCMI_MAIN_CMD_VDEV_MNG,
+ DCMI_MAIN_CMD_SEC,
+ DCMI_MAIN_CMD_EX_COMPUTING = 0x8000,
DCMI_MAIN_CMD_DEVICE_SHARE = 0x8001,
+ DCMI_MAIN_CMD_EX_CERT = 0x8003,
+ DCMI_MAIN_CMD_PCIE = 55,
+ DCMI_MAIN_CMD_SIO = 56,
DCMI_MAIN_CMD_MAX
};
@@ -149,6 +401,49 @@ extern "C" {
DCMI_FREQ_VECTORCORE_CURRENT = 12
};
+ enum dcmi_lp_sub_cmd {
+ DCMI_LP_SUB_CMD_AICORE_VOLTAGE_CURRENT = 0,
+ DCMI_LP_SUB_CMD_HYBIRD_VOLTAGE_CURRENT,
+ DCMI_LP_SUB_CMD_TAISHAN_VOLTAGE_CURRENT,
+ DCMI_LP_SUB_CMD_DDR_VOLTAGE_CURRENT,
+ DCMI_LP_SUB_CMD_ACG,
+ DCMI_LP_SUB_CMD_STATUS,
+ DCMI_LP_SUB_CMD_TOPS_DETAILS,
+ DCMI_LP_SUB_CMD_SET_WORK_TOPS,
+ DCMI_LP_SUB_CMD_GET_WORK_TOPS,
+ DCMI_LP_SUB_CMD_AICORE_FREQREDUC_CAUSE,
+ DCMI_LP_SUB_CMD_GET_POWER_INFO,
+ DCMI_LP_SUB_CMD_SET_IDLE_SWITCH,
+ DCMI_LP_SUB_CMD_MAX
+ };
+
+ struct dcmi_lp_power_info {
+ unsigned int soc_rated_power;
+ unsigned char reserved[32];
+ };
+
+ enum dcmi_component_type {
+ DCMI_COMPONENT_TYPE_NVE = 0,
+ DCMI_COMPONENT_TYPE_XLOADER,
+ DCMI_COMPONENT_TYPE_M3FW,
+ DCMI_COMPONENT_TYPE_UEFI,
+ DCMI_COMPONENT_TYPE_TEE,
+ DCMI_COMPONENT_TYPE_KERNEL,
+ DCMI_COMPONENT_TYPE_DTB,
+ DCMI_COMPONENT_TYPE_ROOTFS,
+ DCMI_COMPONENT_TYPE_IMU,
+ DCMI_COMPONENT_TYPE_IMP,
+ DCMI_COMPONENT_TYPE_AICPU,
+ DCMI_COMPONENT_TYPE_HBOOT1_A,
+ DCMI_COMPONENT_TYPE_HBOOT1_B,
+ DCMI_COMPONENT_TYPE_HBOOT2,
+ DCMI_COMPONENT_TYPE_DDR,
+ DCMI_COMPONENT_TYPE_LP,
+ DCMI_COMPONENT_TYPE_HSM,
+ DCMI_COMPONENT_TYPE_SAFETY_ISLAND,
+ DCMI_COMPONENT_TYPE_HILINK
+ };
+
enum dcmi_reset_channel {
OUTBAND_CHANNEL = 0, // out-of-band reset
INBAND_CHANNEL // in-band reset
@@ -156,24 +451,23 @@ extern "C" {
enum dcmi_boot_status {
DCMI_BOOT_STATUS_UNINIT = 0, // not init
- DCMI_BOOT_STATUS_BIOS, // BIOS starting
- DCMI_BOOT_STATUS_OS, // OS starting
- DCMI_BOOT_STATUS_FINISH // started
+ DCMI_BOOT_STATUS_BIOS, // BIOS starting
+ DCMI_BOOT_STATUS_OS, // OS starting
+ DCMI_BOOT_STATUS_FINISH, // started
+ DCMI_SYSTEM_START_FINISH = 16
};
enum dcmi_event_type {
DCMI_DMS_FAULT_EVENT = 0,
};
- enum dcmi_die_type {
- NDIE,
- VDIE
- };
+ enum dcmi_die_type { NDIE, VDIE, DDIE, INVALID_DIE };
#define DCMI_VDEV_RES_NAME_LEN 16
#define DCMI_VDEV_SIZE 20
#define DCMI_VDEV_FOR_RESERVE 32
#define DCMI_SOC_SPLIT_MAX 32
+#define DCMI_PCIE_SUB_CMD_PCIE_ERROR_INFO 1
#define DCMI_MAX_EVENT_NAME_LENGTH 256
#define DCMI_MAX_EVENT_DATA_LENGTH 32
#define DCMI_EVENT_FILTER_FLAG_EVENT_ID (1UL << 0)
@@ -306,7 +600,12 @@ extern "C" {
unsigned long long alarm_raised_time;
char event_name[DCMI_MAX_EVENT_NAME_LENGTH]; /* Event description */
char additional_info[DCMI_MAX_EVENT_DATA_LENGTH]; /* Additional event information */
- unsigned char resv[DCMI_MAX_EVENT_RESV_LENGTH]; /**< Reserves 32 bytes */
+ unsigned char os_id;
+ unsigned char resv_1[1];
+ unsigned short node_type_ex;
+ unsigned short sub_node_type_ex;
+ unsigned char resv_2[2];
+ unsigned char resv[DCMI_MAX_EVENT_RESV_LENGTH - 8]; /**< Reserves 24 bytes */
};
struct dcmi_event {
@@ -346,14 +645,238 @@ extern "C" {
unsigned int slot_id; // slot_id indicates pcie slot ID of the chip
};
+ struct dcmi_elabel_info {
+ char product_name[MAX_LENTH];
+ char model[MAX_LENTH];
+ char manufacturer[MAX_LENTH];
+ char manufacturer_date[MAX_LENTH];
+ char serial_number[MAX_LENTH];
+ };
+
+ struct dcmi_cgroup_info {
+ unsigned long limit_in_bytes;
+ unsigned long max_usage_in_bytes;
+ unsigned long usage_in_bytes;
+ };
+
+ struct dcmi_llc_perf {
+ unsigned int wr_hit_rate;
+ unsigned int rd_hit_rate;
+ unsigned int throughput;
+ };
+
struct dsmi_hbm_info_stru {
- unsigned long long memory_size; /**< HBM total size, KB */
+ unsigned long long memory_size; /**< HBM total size, MB */
unsigned int freq; /**< HBM freq, MHZ */
- unsigned long long memory_usage; /**< HBM memory_usage, KB */
+ unsigned long long memory_usage; /**< HBM memory_usage, MB */
int temp; /**< HBM temperature */
unsigned int bandwith_util_rate;
};
+#define AGENTDRV_PROF_DATA_NUM 3
+ struct dcmi_pcie_link_bandwidth_info {
+ int profiling_time;
+ unsigned int tx_p_bw[AGENTDRV_PROF_DATA_NUM];
+ unsigned int tx_np_bw[AGENTDRV_PROF_DATA_NUM];
+ unsigned int tx_cpl_bw[AGENTDRV_PROF_DATA_NUM];
+ unsigned int tx_np_lantency[AGENTDRV_PROF_DATA_NUM];
+ unsigned int rx_p_bw[AGENTDRV_PROF_DATA_NUM];
+ unsigned int rx_np_bw[AGENTDRV_PROF_DATA_NUM];
+ unsigned int rx_cpl_bw[AGENTDRV_PROF_DATA_NUM];
+ };
+
+ struct dcmi_hccs_bandwidth_info {
+ int profiling_time;
+ double total_txbw;
+ double total_rxbw;
+ double tx_bandwidth[DCMI_HCCS_MAX_PCS_NUM];
+ double rx_bandwidth[DCMI_HCCS_MAX_PCS_NUM];
+ };
+
+ enum dcmi_entire_ub_status {
+ DCMI_UB_ALL_PORT_NO_LINK = 0,
+ DCMI_UB_ALL_PORT_LINK,
+ DCMI_UB_PARTIAL_PORT_LINK,
+ DCMI_UB_NO_NEED_LINK,
+ };
+
+ enum dcmi_ub_port_status {
+ DCMI_UB_PORT_STATUS_NONE_LANE = 0,
+ DCMI_UB_PORT_STATUS_FULL_LANE,
+ DCMI_UB_PORT_STATUS_PARTIAL_LANE,
+ DCMI_UB_PORT_STATUS_INITIAL,
+ };
+
+ struct dcmi_ub_port_link_status {
+ enum dcmi_entire_ub_status ub_link_status;
+ enum dcmi_ub_port_status ub_port_status[DCMI_UB_PORT_NUM];
+ };
+
+ struct dcmi_ub_bandwidth_info {
+ unsigned int tx_bandwidth;
+ unsigned int rx_bandwidth;
+ unsigned int reserved[2];
+ };
+
+ struct dcmi_ub_port_info {
+ int udie_id;
+ int port_id;
+ };
+
+ struct dcmi_network_rdma_bandwidth_info {
+ unsigned int tx_bandwidth;
+ unsigned int rx_bandwidth;
+ };
+
+ struct dcmi_port_pkt_stats_info {
+ unsigned int port_id;
+ unsigned int is_uboe_port;
+ union {
+ struct {
+ unsigned long long ub_ipv4_pkt_cnt_rx;
+ unsigned long long ub_ipv6_pkt_cnt_rx;
+ unsigned long long unic_ipv4_pkt_cnt_rx;
+ unsigned long long unic_ipv6_pkt_cnt_rx;
+ unsigned long long ub_compact_pkt_cnt_rx;
+ unsigned long long ub_umoc_ctph_cnt_rx;
+ unsigned long long ub_umoc_ntph_cnt_rx;
+ unsigned long long ub_mem_pkt_cnt_rx;
+ unsigned long long unknown_pkt_cnt_rx;
+ unsigned long long drop_ind_cnt_rx;
+ unsigned long long err_ind_cnt_rx;
+ unsigned long long to_host_pkt_cnt_rx;
+ unsigned long long to_imp_pkt_cnt_rx;
+ unsigned long long to_mar_pkt_cnt_rx;
+ unsigned long long to_link_pkt_cnt_rx;
+ unsigned long long to_noc_pkt_cnt_rx;
+ unsigned long long route_err_cnt_rx;
+ unsigned long long out_err_cnt_rx;
+ unsigned long long length_err_cnt_rx;
+ unsigned long long rx_busi_flit_num;
+ unsigned long long rx_send_ack_flit;
+ unsigned long long ub_ipv4_pkt_cnt_tx;
+ unsigned long long ub_ipv6_pkt_cnt_tx;
+ unsigned long long unic_ipv4_pkt_cnt_tx;
+ unsigned long long unic_ipv6_pkt_cnt_tx;
+ unsigned long long ub_compact_pkt_cnt_tx;
+ unsigned long long ub_umoc_ctph_cnt_tx;
+ unsigned long long ub_umoc_ntph_cnt_tx;
+ unsigned long long ub_mem_pkt_cnt_tx;
+ unsigned long long unknown_pkt_cnt_tx;
+ unsigned long long drop_ind_cnt_tx;
+ unsigned long long err_ind_cnt_tx;
+ unsigned long long lpbk_ind_cnt_tx;
+ unsigned long long out_err_cnt_tx;
+ unsigned long long length_err_cnt_tx;
+ unsigned long long tx_busi_flit_num;
+ unsigned long long tx_recv_ack_flit;
+ unsigned long long retry_req_sum;
+ unsigned long long retry_ack_sum;
+ unsigned long long crc_error_sum;
+ struct {
+ unsigned long long core_mib_rxpausepkts;
+ unsigned long long core_mib_txpausepkts;
+ unsigned long long core_mib_rxpfcpkts;
+ unsigned long long core_mib_txpfcpkts;
+ unsigned long long core_mib_rxbadpkts;
+ unsigned long long core_mib_txbadpkts;
+ unsigned long long core_mib_rxbadoctets;
+ unsigned long long core_mib_txbadoctets;
+ } uboe;
+ };
+ unsigned long long pkt_num[DCMI_PORT_PKT_STATS_NUM];
+ };
+ unsigned char reserved[128];
+ };
+
+ struct dcmi_credit_info {
+ unsigned int link_alloc_port_share_credit;
+ unsigned int link_cur_used_port_share_credit;
+ unsigned int link_alloc_vl_pri_credit[16];
+ unsigned int link_cur_used_pri_credit[16];
+ };
+
+ struct dcmi_netdev_list_info {
+ int netdev_nums;
+ char netdev_name[NETDEV_MAX_NUM][NETDEV_NAME_MAX_LEN];
+ };
+
+ struct dcmi_tc_stat_data {
+ unsigned long long tc_tx[TC_MAX_NUM];
+ unsigned long long tc_rx[TC_MAX_NUM];
+ unsigned long long reserved[TC_MAX_NUM];
+ };
+
+ struct dcmi_network_pkt_stats_info {
+ unsigned long long mac_tx_mac_pause_num;
+ unsigned long long mac_rx_mac_pause_num;
+ unsigned long long mac_tx_pfc_pkt_num;
+ unsigned long long mac_tx_pfc_pri0_pkt_num;
+ unsigned long long mac_tx_pfc_pri1_pkt_num;
+ unsigned long long mac_tx_pfc_pri2_pkt_num;
+ unsigned long long mac_tx_pfc_pri3_pkt_num;
+ unsigned long long mac_tx_pfc_pri4_pkt_num;
+ unsigned long long mac_tx_pfc_pri5_pkt_num;
+ unsigned long long mac_tx_pfc_pri6_pkt_num;
+ unsigned long long mac_tx_pfc_pri7_pkt_num;
+ unsigned long long mac_rx_pfc_pkt_num;
+ unsigned long long mac_rx_pfc_pri0_pkt_num;
+ unsigned long long mac_rx_pfc_pri1_pkt_num;
+ unsigned long long mac_rx_pfc_pri2_pkt_num;
+ unsigned long long mac_rx_pfc_pri3_pkt_num;
+ unsigned long long mac_rx_pfc_pri4_pkt_num;
+ unsigned long long mac_rx_pfc_pri5_pkt_num;
+ unsigned long long mac_rx_pfc_pri6_pkt_num;
+ unsigned long long mac_rx_pfc_pri7_pkt_num;
+ unsigned long long mac_tx_total_pkt_num;
+ unsigned long long mac_tx_total_oct_num;
+ unsigned long long mac_tx_bad_pkt_num;
+ unsigned long long mac_tx_bad_oct_num;
+ unsigned long long mac_rx_total_pkt_num;
+ unsigned long long mac_rx_total_oct_num;
+ unsigned long long mac_rx_bad_pkt_num;
+ unsigned long long mac_rx_bad_oct_num;
+ unsigned long long mac_rx_fcs_err_pkt_num;
+ unsigned long long roce_rx_rc_pkt_num;
+ unsigned long long roce_rx_all_pkt_num;
+ unsigned long long roce_rx_err_pkt_num;
+ unsigned long long roce_tx_rc_pkt_num;
+ unsigned long long roce_tx_all_pkt_num;
+ unsigned long long roce_tx_err_pkt_num;
+ unsigned long long roce_cqe_num;
+ unsigned long long roce_rx_cnp_pkt_num;
+ unsigned long long roce_tx_cnp_pkt_num;
+ unsigned long long roce_err_ack_num;
+ unsigned long long roce_err_psn_num;
+ unsigned long long roce_verification_err_num;
+ unsigned long long roce_err_qp_status_num;
+ unsigned long long roce_new_pkt_rty_num;
+ unsigned long long roce_ecn_db_num;
+ unsigned long long nic_tx_all_pkg_num;
+ unsigned long long nic_tx_all_oct_num;
+ unsigned long long nic_rx_all_pkg_num;
+ unsigned long long nic_rx_all_oct_num;
+ long tv_sec;
+ long tv_usec;
+ unsigned char reserved[64];
+ };
+
+ struct port_info {
+ int port_index;
+ int mode;
+ };
+
+ struct die_port_list_info {
+ int die_index;
+ int port_nums;
+ struct port_info port_list_data[MAX_PORT_NUMS];
+ };
+
+ struct dcmi_port_list_info {
+ int die_nums;
+ struct die_port_list_info die_list_data[MAX_DIE_NUMS];
+ };
+
#define DCMI_VERSION_1
#define DCMI_VERSION_2
@@ -361,47 +884,148 @@ extern "C" {
DCMIDLLEXPORT int dcmi_init(void);
+ DCMIDLLEXPORT int dcmi_get_dcmi_version(char *dcmi_ver, unsigned int len) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_driver_version(char *driver_ver, unsigned int len) DCMI_WEAK;
+
DCMIDLLEXPORT int dcmi_get_card_list(int *card_num, int *card_list, int list_len);
DCMIDLLEXPORT int dcmi_get_device_num_in_card(int card_id, int *device_num);
DCMIDLLEXPORT int dcmi_get_device_id_in_card(int card_id, int *device_id_max, int *mcu_id, int *cpu_id);
- DCMIDLLEXPORT int dcmi_get_device_type(int card_id, int device_id, enum dcmi_unit_type *device_type);
+ DCMIDLLEXPORT int dcmi_get_device_type(int card_id, int device_id, enum dcmi_unit_type *device_type) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_pcie_info_v2(int card_id, int device_id,
+ struct dcmi_pcie_info_all *pcie_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_pcie_info(int card_id, int device_id, struct dcmi_pcie_info *pcie_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_chip_info_v2(int card_id, int device_id,
+ struct dcmi_chip_info_v2 *chip_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_chip_info(int card_id, int device_id, struct dcmi_chip_info *chip_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_aicore_info(int card_id, int device_id,
+ struct dcmi_aicore_info *aicore_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_power_info(int card_id, int device_id, int *power) DCMI_WEAK;
- DCMIDLLEXPORT int dcmi_get_device_pcie_info_v2(int card_id, int device_id, struct dcmi_pcie_info_all *pcie_info);
+ DCMIDLLEXPORT int dcmi_get_device_health(int card_id, int device_id, unsigned int *health) DCMI_WEAK;
- DCMIDLLEXPORT int dcmi_get_device_chip_info(int card_id, int device_id, struct dcmi_chip_info *chip_info);
+ DCMIDLLEXPORT int dcmi_get_driver_health(unsigned int *health) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmi_get_driver_errorcode(int *error_count, unsigned int *error_code_list,
+ unsigned int list_len) DCMI_WEAK;
- DCMIDLLEXPORT int dcmi_get_device_power_info(int card_id, int device_id, int *power);
+ DCMIDLLEXPORT int dcmi_get_device_errorcode_v2(int card_id, int device_id, int *error_count,
+ unsigned int *error_code_list, unsigned int list_len) DCMI_WEAK;
- DCMIDLLEXPORT int dcmi_get_device_health(int card_id, int device_id, unsigned int *health);
+ DCMIDLLEXPORT int dcmi_get_device_errorcode_string(int card_id, int device_id, unsigned int error_code,
+ unsigned char *error_info, int buf_size) DCMI_WEAK;
- DCMIDLLEXPORT int dcmi_get_device_errorcode_v2(
- int card_id, int device_id, int *error_count, unsigned int *error_code_list, unsigned int list_len);
+ DCMIDLLEXPORT int dcmi_get_device_temperature(int card_id, int device_id, int *temperature) DCMI_WEAK;
- DCMIDLLEXPORT int dcmi_get_device_temperature(int card_id, int device_id, int *temperature);
+ DCMIDLLEXPORT int dcmi_get_device_voltage(int card_id, int device_id, unsigned int *voltage) DCMI_WEAK;
- DCMIDLLEXPORT int dcmi_get_device_voltage(int card_id, int device_id, unsigned int *voltage);
+ DCMIDLLEXPORT int dcmi_get_device_board_info(int card_id, int device_id,
+ struct dcmi_board_info *board_info) DCMI_WEAK;
- DCMIDLLEXPORT int dcmi_get_device_frequency(
- int card_id, int device_id, enum dcmi_freq_type input_type, unsigned int *frequency);
+ DCMIDLLEXPORT int dcmi_get_device_board_id(int card_id, int device_id, unsigned int *board_id) DCMI_WEAK;
- DCMIDLLEXPORT int dcmi_get_device_hbm_info(int card_id, int device_id, struct dcmi_hbm_info *hbm_info);
+ DCMIDLLEXPORT int dcmi_get_mainboard_id(int card_id, int device_id, unsigned int *mainboard_id) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_card_pcie_slot(int card_id, int *pcie_slot) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_chip_slot(int card_id, int device_id, int *chip_pos_id) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_first_power_on_date(int card_id, unsigned int *first_power_on_date) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_aicpu_count_info(int card_id, int device_id, unsigned char *count_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_cpu_num_config(int card_id, int device_id, unsigned char *buf,
+ unsigned int buf_size) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_cpu_freq_info(int card_id, int device_id, int *enable_flag) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_p2p_enable(int card_id, int device_id, int *enable_flag) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_aicpu_info(int card_id, int device_id,
+ struct dcmi_aicpu_info *aicpu_info) DCMI_WEAK;
+
+ /* Newer physical-device spelling; older releases may only export the
+ * dcmi_get_system_time alias below. */
+ DCMIDLLEXPORT int dcmi_get_device_system_time(int card_id, int device_id, unsigned int *system_time) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_multi_utilization_rate(int card_id, int device_id,
+ struct dcmi_multi_utilization_info *util_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_sensor_info(int card_id, int device_id, enum dcmi_manager_sensor_id sensor_id,
+ union dcmi_sensor_info *sensor_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_ecc_info(int card_id, int device_id, enum dcmi_device_type input_type,
+ struct dcmi_ecc_info *device_ecc_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_pcie_error_cnt(int card_id, int device_id,
+ struct dcmi_chip_pcie_err_rate *pcie_err_code_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_frequency(int card_id, int device_id, enum dcmi_freq_type input_type,
+ unsigned int *frequency) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_hbm_info(int card_id, int device_id, struct dcmi_hbm_info *hbm_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_hbm_product_info(int card_id, int device_id,
+ struct dcmi_hbm_product_info *hbm_product_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_memory_info_v2(int card_id, int device_id,
+ struct dcmi_memory_info *memory_info) DCMI_WEAK;
DCMIDLLEXPORT int dcmi_get_device_memory_info_v3(int card_id, int device_id,
- struct dcmi_get_memory_info_stru *memory_info);
+ struct dcmi_get_memory_info_stru *memory_info) DCMI_WEAK;
- DCMIDLLEXPORT int dcmi_get_device_utilization_rate(
- int card_id, int device_id, int input_type, unsigned int *utilization_rate);
+ DCMIDLLEXPORT int dcmi_get_device_utilization_rate(int card_id, int device_id, int input_type,
+ unsigned int *utilization_rate) DCMI_WEAK;
- DCMIDLLEXPORT int dcmi_get_device_info(
- int card_id, int device_id, enum dcmi_main_cmd main_cmd, unsigned int sub_cmd, void *buf, unsigned int *size);
+ DCMIDLLEXPORT int dcmi_get_device_info(int card_id, int device_id, enum dcmi_main_cmd main_cmd, unsigned int sub_cmd,
+ void *buf, unsigned int *size) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_component_static_version(int card_id, int device_id,
+ enum dcmi_component_type component_type,
+ unsigned char *version_str, unsigned int len) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_component_count(int card_id, int device_id,
+ unsigned int *component_count) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_component_list(int card_id, int device_id,
+ enum dcmi_component_type *component_table,
+ unsigned int component_count) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_elabel_info(int card_id, int device_id,
+ struct dcmi_elabel_info *elabel_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_cgroup_info(int card_id, int device_id, struct dcmi_cgroup_info *cg_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_llc_perf_para(int card_id, int device_id,
+ struct dcmi_llc_perf *perf_para) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_share_enable(int card_id, int device_id, int *enable_flag) DCMI_WEAK;
DCMIDLLEXPORT int dcmi_get_device_ip(int card_id, int device_id, enum dcmi_port_type input_type, int port_id,
struct dcmi_ip_addr *ip, struct dcmi_ip_addr *mask);
- DCMIDLLEXPORT int dcmi_get_device_network_health(int card_id, int device_id, enum dcmi_rdfx_detect_result *result);
+ DCMIDLLEXPORT int dcmi_get_device_network_health(int card_id, int device_id,
+ enum dcmi_rdfx_detect_result *result) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_outband_channel_state(int card_id, int device_id, int *channel_state) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_current_fault_event(int card_id, int device_id, struct dcmi_event *event_buf,
+ int input_event_buf_length, int *output_event_cnt) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_compatibility(int card_id, int device_id,
+ enum dcmi_device_compat *compatibility) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_fan_count(int card_id, int device_id, int *count) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_fan_speed(int card_id, int device_id, int fan_id, int *speed) DCMI_WEAK;
DCMIDLLEXPORT int dcmi_get_device_logic_id(int *device_logic_id, int card_id, int device_id);
@@ -414,7 +1038,8 @@ extern "C" {
DCMIDLLEXPORT int dcmi_get_device_logicid_from_phyid(unsigned int phyid, unsigned int *logicid);
- DCMIDLLEXPORT int dcmi_get_card_id_device_id_from_logicid(int *card_id, int *device_id, unsigned int device_logic_id);
+ DCMIDLLEXPORT int dcmi_get_card_id_device_id_from_logicid(int *card_id, int *device_id,
+ unsigned int device_logic_id) DCMI_WEAK;
DCMIDLLEXPORT int dcmi_get_card_id_device_id_from_phyid(int *card_id, int *device_id, unsigned int device_phy_id);
@@ -422,21 +1047,159 @@ extern "C" {
DCMIDLLEXPORT int dcmi_set_device_reset(int card_id, int device_id, enum dcmi_reset_channel channel_type);
- DCMIDLLEXPORT int dcmi_get_device_boot_status(int card_id, int device_id, enum dcmi_boot_status *boot_status);
+ DCMIDLLEXPORT int dcmi_get_device_boot_status(int card_id, int device_id,
+ enum dcmi_boot_status *boot_status) DCMI_WEAK;
DCMIDLLEXPORT int dcmi_subscribe_fault_event(int card_id, int device_id, struct dcmi_event_filter filter);
DCMIDLLEXPORT int dcmi_get_npu_work_mode(int card_id, unsigned char *work_mode);
- DCMIDLLEXPORT int dcmi_get_device_die_v2(
- int card_id, int device_id, enum dcmi_die_type input_type, struct dcmi_die_id *die_id);
-
- DCMIDLLEXPORT int dcmi_get_device_resource_info (int card_id, int device_id, struct dcmi_proc_mem_info *proc_info,
- int *proc_num);
-
- DCMIDLLEXPORT int dcmi_get_device_board_info (int card_id, int device_id, struct dcmi_board_info *board_info);
-
- DCMIDLLEXPORT int dcmi_get_hbm_info(int card_id, int device_id, struct dsmi_hbm_info_stru *device_hbm_info);
+ DCMIDLLEXPORT int dcmi_get_device_die_v2(int card_id, int device_id, enum dcmi_die_type input_type,
+ struct dcmi_die_id *die_id) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_resource_info(int card_id, int device_id, struct dcmi_proc_mem_info *proc_info,
+ int *proc_num) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_dvpp_ratio_info(int card_id, int device_id,
+ struct dcmi_dvpp_ratio *usage) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_hbm_info(int card_id, int device_id, struct dsmi_hbm_info_stru *device_hbm_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int
+ dcmi_get_pcie_link_bandwidth_info(int card_id, int device_id,
+ struct dcmi_pcie_link_bandwidth_info *pcie_link_bandwidth_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_hccs_link_bandwidth_info(int card_id, int device_id,
+ struct dcmi_hccs_bandwidth_info *hccs_bandwidth_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_ub_realtime_bandwidth_info(int card_id, int device_id, unsigned int profiling_time,
+ struct dcmi_ub_port_info *ub_port_info,
+ struct dcmi_ub_bandwidth_info *ub_bandwidth_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_ub_port_link_status_info(int card_id, int device_id,
+ struct dcmi_ub_port_link_status *ub_status) DCMI_WEAK;
+
+ /* Logical-device API introduced by newer CANN releases. These symbols are
+ * weak on purpose so the same binary remains compatible with older DCMI
+ * libraries that only export the card/device API above. */
+ DCMIDLLEXPORT int dcmiv2_init(void) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmiv2_get_driver_version(char *driver_ver, unsigned int len) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_dcmi_version(char *dcmi_ver, unsigned int len) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_list(int *device_list, int *device_cnt, int list_len) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmiv2_get_device_chip_info(int dev_id, struct dcmi_chip_info_v2 *chip_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_pcie_info(int dev_id, struct dcmi_pcie_info_all *pcie_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_ub_id_info(int dev_id, struct dcmi_ub_id_info *ub_id_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_board_info(int dev_id, struct dcmi_board_info *board_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_elabel_info(int dev_id, struct dcmi_elabel_info *elabel_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_hbm_product_info(int dev_id,
+ struct dcmi_hbm_product_info *hbm_product_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmiv2_get_driver_health(unsigned int *health) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_driver_error_code_list(int *error_count, unsigned int *error_code_list,
+ unsigned int list_len) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_error_code_list(int dev_id, int *error_count, unsigned int *error_code_list,
+ unsigned int list_len) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmiv2_get_device_error_info(int dev_id, unsigned int error_code, unsigned char *error_info,
+ int buf_size) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_flash_cnt(int dev_id, unsigned int *flash_cnt) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_flash_info(int dev_id, unsigned int flash_index,
+ struct dcmi_flash_info *flash_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_health(int dev_id, unsigned int *health) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_die_id(int dev_id, enum dcmi_die_type input_type,
+ struct dcmi_die_id *die_id) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_power_info(int dev_id, int *power_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_voltage(int dev_id, unsigned int *voltage) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_temperature(int dev_id, int *temperature) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_aicore_info(int dev_id, struct dcmi_aicore_info *aicore_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_aicpu_info(int dev_id, struct dcmi_aicpu_info *aicpu_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_type(int dev_id, enum dcmi_unit_type *device_type) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_board_id(int dev_id, unsigned int *board_id) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_mainboard_id(int dev_id, unsigned int *mainboard_id) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_pcie_slot_id(int dev_id, int *pcie_slot) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_ub_slot_id(int dev_id, int *ub_slot) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_slot_id_and_chip_id_by_dev_id(int dev_id, unsigned int *slot_id,
+ unsigned int *chip_id) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_group_intra_id_by_dev_id(int dev_id, unsigned int *group_intra_id) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_share_enable(int dev_id, unsigned int *enable_flag) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmiv2_get_device_ecc_info(int dev_id, enum dcmi_device_type input_type,
+ struct dcmi_ecc_info *device_ecc_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_frequency(int dev_id, enum dcmi_freq_type input_type,
+ unsigned int *frequency) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_hbm_info(int dev_id, struct dcmi_hbm_info *hbm_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_utilization_rate(int dev_id, int input_type,
+ unsigned int *utilization_rate) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_sensor_info(int dev_id, enum dcmi_manager_sensor_id sensor_id,
+ union dcmi_sensor_info *sensor_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_multi_utilization_rate(int dev_id,
+ struct dcmi_multi_utilization_info *util_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_pcie_error_cnt(int dev_id,
+ struct dcmi_chip_pcie_err_rate *pcie_err_code_info) DCMI_WEAK;
+ DCMIDLLEXPORT int
+ dcmiv2_get_pcie_link_bandwidth_info(int dev_id,
+ struct dcmi_pcie_link_bandwidth_info *pcie_link_bandwidth_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_proc_mem_info(int dev_id, struct dcmi_proc_mem_info *proc_info,
+ int *proc_num) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_multi_ecc_time_info(int dev_id,
+ struct dcmi_multi_ecc_time_data *multi_ecc_time_data) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_multi_ecc_record_info(int dev_id, struct dcmi_ecc_record_type type,
+ unsigned int *ecc_count,
+ struct dcmi_ecc_common_data *ecc_common_data_s) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_computing_power_info(int dev_id, int type,
+ struct dsmi_computing_power_info *computing_power) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmiv2_get_device_current_fault_event(int dev_id, struct dcmi_event *event_buf,
+ int input_event_buf_length, int *output_event_cnt) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_info(int dev_id, enum dcmi_main_cmd main_cmd, unsigned int sub_cmd, void *buf,
+ unsigned int *size) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_cgroup_info(int dev_id, struct dcmi_cgroup_info *cg_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_llc_perf_para(int dev_id, struct dcmi_llc_perf *perf_para) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_component_static_version(int dev_id, enum dcmi_component_type component_type,
+ unsigned char *version_str, unsigned int len) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_component_cnt(int dev_id, unsigned int *component_count) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_component_list(int dev_id, enum dcmi_component_type *component_table,
+ unsigned int component_count) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_boot_status(int dev_id, enum dcmi_boot_status *boot_status) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_compatibility(int dev_id, enum dcmi_device_compat *compatibility) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_network_health(int dev_id, enum dcmi_rdfx_detect_result *result) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_netdev_health(int dev_id, const char *netdev_name, unsigned int netdev_name_len,
+ enum dcmi_rdfx_detect_result *result) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_outband_channel_state(int dev_id, int *channel_state) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmiv2_get_ub_port_link_status(int dev_id, struct dcmi_ub_port_link_status *ub_status) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmiv2_get_ub_realtime_bandwidth_info(int dev_id, unsigned int profiling_time,
+ struct dcmi_ub_port_info *ub_port_info,
+ struct dcmi_ub_bandwidth_info *ub_bandwidth_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmiv2_get_device_port_list_info(int dev_id, struct dcmi_port_list_info *port_list_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmiv2_get_port_pkt_stats_info(int dev_id, struct dcmi_ub_port_info *ub_port_info,
+ struct dcmi_port_pkt_stats_info *port_pkt_stats_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int
+ dcmiv2_get_rdma_bandwidth_info(int dev_id, int port_id, unsigned int profiling_time,
+ struct dcmi_network_rdma_bandwidth_info *network_rdma_bandwidth_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int
+ dcmiv2_get_netdev_pkt_stats_info(int dev_id, int port_id,
+ struct dcmi_network_pkt_stats_info *network_pkt_stats_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmiv2_get_device_netdev_list_info(int dev_id, struct dcmi_netdev_list_info *netdev_list) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_affinity_cpu_info_by_dev_id(int dev_id, char *affinity_cpu, int *len) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_device_system_time(int dev_id, unsigned int *system_time) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmiv2_get_vrd_version(int dev_id, char *version, int len) DCMI_WEAK;
+
+ DCMIDLLEXPORT int
+ dcmi_get_rdma_bandwidth_info(int card_id, int device_id, int port_id, unsigned int profiling_time,
+ struct dcmi_network_rdma_bandwidth_info *network_rdma_bandwidth_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int
+ dcmi_get_netdev_pkt_stats_info(int card_id, int device_id, int port_id,
+ struct dcmi_network_pkt_stats_info *network_pkt_stats_info) DCMI_WEAK;
#endif
@@ -447,10 +1210,39 @@ extern "C" {
struct dcmi_memory_info_stru {
unsigned long long memory_size;
unsigned int freq;
- unsigned int utilize;
+ unsigned int utiliza;
+ };
+
+ struct dsmi_computing_power_info {
+ unsigned int data1;
+ unsigned int reserve[3];
};
- DCMIDLLEXPORT int dcmi_get_memory_info(int card_id, int device_id, struct dcmi_memory_info_stru *device_memory_info);
+ DCMIDLLEXPORT int dcmi_get_memory_info(int card_id, int device_id,
+ struct dcmi_memory_info_stru *device_memory_info) DCMI_WEAK;
+
+ DCMIDLLEXPORT int dcmi_get_device_flash_count(int card_id, int device_id, unsigned int *flash_count) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmi_get_device_flash_info_v2(int card_id, int device_id, unsigned int flash_index,
+ struct dcmi_flash_info *flash_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmi_get_device_flash_info(int card_id, int device_id, unsigned int flash_index,
+ struct dcmi_flash_info_stru *flash_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmi_get_multi_ecc_time_info_v2(int card_id, int device_id,
+ struct dcmi_multi_ecc_time_data *multi_ecc_time_data) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmi_get_multi_ecc_record_info_v2(int card_id, int device_id, struct dcmi_ecc_record_type type,
+ unsigned int *ecc_count,
+ struct dcmi_ecc_common_data *ecc_common_data_s) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmi_get_affinity_cpu_info_by_device_id(int card_id, int device_id, char *affinity_cpu,
+ int *length) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmi_get_netdev_tc_stat_info(int card_id, int device_id,
+ struct dcmi_tc_stat_data *network_tc_stat_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmi_get_vrd_version(int card_id, char *version, int len) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmi_get_system_time(int card_id, int device_id, unsigned int *system_time) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmi_get_aicore_info(int card_id, int device_id,
+ struct dsmi_aicore_info_stru *aicore_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmi_get_aicpu_info(int card_id, int device_id, struct dsmi_aicpu_info_stru *aicpu_info) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmi_get_p2p_enable(int card_id, int device_id, int *enable_flag) DCMI_WEAK;
+ DCMIDLLEXPORT int dcmi_get_computing_power_info(int card_id, int device_id, int type,
+ struct dsmi_computing_power_info *computing_power) DCMI_WEAK;
DCMIDLLEXPORT int dcmi_get_device_errorcode(
int card_id, int device_id, int *error_count, unsigned int *error_code, int *error_width);
diff --git a/include/nvtop/extract_gpuinfo_common.h b/include/nvtop/extract_gpuinfo_common.h
index 9e4d1c9d..3023b08d 100644
--- a/include/nvtop/extract_gpuinfo_common.h
+++ b/include/nvtop/extract_gpuinfo_common.h
@@ -53,6 +53,7 @@
#define GPUINFO_STATIC_FIELD_VALID(structPtr, field) VALUE_IS_VALID(structPtr, field, gpuinfo_)
enum gpuinfo_static_info_valid {
gpuinfo_device_name_valid = 0,
+ gpuinfo_memory_type_valid,
gpuinfo_max_pcie_gen_valid,
gpuinfo_max_pcie_link_width_valid,
gpuinfo_temperature_shutdown_threshold_valid,
@@ -61,13 +62,118 @@ enum gpuinfo_static_info_valid {
gpuinfo_l2cache_size_valid,
gpuinfo_n_exec_engines_valid,
gpuinfo_engine_count_valid,
+ gpuinfo_chip_type_valid,
+ gpuinfo_chip_version_valid,
+ gpuinfo_npu_name_valid,
+ gpuinfo_board_id_valid,
+ gpuinfo_pcb_id_valid,
+ gpuinfo_bom_id_valid,
+ gpuinfo_slot_id_valid,
+ gpuinfo_mainboard_id_valid,
+ gpuinfo_pcie_slot_id_valid,
+ gpuinfo_ub_slot_id_valid,
+ gpuinfo_ub_device_id_valid,
+ gpuinfo_ub_vendor_id_valid,
+ gpuinfo_ub_module_vendor_id_valid,
+ gpuinfo_ub_module_id_valid,
+ gpuinfo_chip_id_valid,
+ gpuinfo_chip_slot_valid,
+ gpuinfo_group_intra_id_valid,
+ gpuinfo_first_power_on_date_valid,
+ gpuinfo_aicpu_count_valid,
+ gpuinfo_cpu_config_aicpu_valid,
+ gpuinfo_cpu_config_ctrlcpu_valid,
+ gpuinfo_cpu_config_datacpu_valid,
+ gpuinfo_cpu_freq_mode_valid,
+ gpuinfo_driver_version_valid,
+ gpuinfo_dcmi_version_valid,
+ gpuinfo_firmware_version_valid,
+ gpuinfo_hbm_manufacturer_id_valid,
+ gpuinfo_elabel_product_name_valid,
+ gpuinfo_elabel_model_valid,
+ gpuinfo_elabel_manufacturer_valid,
+ gpuinfo_elabel_manufacturer_date_valid,
+ gpuinfo_elabel_serial_number_valid,
+ gpuinfo_die_id_valid,
+ gpuinfo_vrd_version_valid,
+ gpuinfo_affinity_cpu_valid,
+ gpuinfo_flash_inventory_valid,
+ gpuinfo_netdev_names_valid,
gpuinfo_static_info_count,
};
#define MAX_DEVICE_NAME 128
+#define MAX_DEVICE_METADATA 32
+#define MAX_VERSION_STRING 256
+#define GPUINFO_MAX_ERROR_CODES 16
+#define GPUINFO_MAX_FAULT_EVENTS 8
+#define GPUINFO_MAX_FLASHES 8
+#define GPUINFO_MAX_NETDEVS 8
+#define GPUINFO_NETDEV_NAME_LEN 16
+#define GPUINFO_MAX_ECC_RECORDS 64
+
+struct gpuinfo_fault_event {
+ unsigned int event_id;
+ unsigned int severity;
+ unsigned int assertion;
+ unsigned long long alarm_raised_time;
+ char event_name[MAX_VERSION_STRING];
+ char additional_info[64];
+};
+
+struct gpuinfo_flash_info {
+ unsigned long long flash_id;
+ unsigned short device_id;
+ unsigned short vendor;
+ unsigned int state;
+ unsigned long long size;
+ unsigned int sector_count;
+ unsigned short manufacturer_id;
+};
struct gpuinfo_static_info {
char device_name[MAX_DEVICE_NAME];
+ char memory_type[8];
+ char chip_type[MAX_DEVICE_METADATA];
+ char chip_version[MAX_DEVICE_METADATA];
+ char npu_name[MAX_DEVICE_METADATA];
+ char driver_version[MAX_VERSION_STRING];
+ char dcmi_version[MAX_VERSION_STRING];
+ char firmware_version[MAX_VERSION_STRING];
+ char elabel_product_name[MAX_VERSION_STRING];
+ char elabel_model[MAX_VERSION_STRING];
+ char elabel_manufacturer[MAX_VERSION_STRING];
+ char elabel_manufacturer_date[MAX_VERSION_STRING];
+ char elabel_serial_number[MAX_VERSION_STRING];
+ char die_id[MAX_VERSION_STRING];
+ char vrd_version[MAX_VERSION_STRING];
+ char affinity_cpu[MAX_VERSION_STRING];
+ unsigned board_id;
+ unsigned pcb_id;
+ unsigned bom_id;
+ unsigned slot_id;
+ unsigned mainboard_id;
+ unsigned pcie_slot_id;
+ unsigned ub_slot_id;
+ unsigned ub_device_id;
+ unsigned ub_vendor_id;
+ unsigned ub_module_vendor_id;
+ unsigned ub_module_id;
+ unsigned chip_id;
+ unsigned chip_slot;
+ unsigned group_intra_id;
+ unsigned first_power_on_date;
+ unsigned aicpu_count;
+ unsigned cpu_config_aicpu;
+ unsigned cpu_config_ctrlcpu;
+ unsigned cpu_config_datacpu;
+ unsigned cpu_freq_mode;
+ unsigned hbm_manufacturer_id;
+ unsigned flash_count;
+ unsigned flash_inventory_count;
+ struct gpuinfo_flash_info flashes[GPUINFO_MAX_FLASHES];
+ unsigned netdev_count;
+ char netdev_names[GPUINFO_MAX_NETDEVS][GPUINFO_NETDEV_NAME_LEN];
unsigned max_pcie_gen;
unsigned max_pcie_link_width;
unsigned temperature_shutdown_threshold;
@@ -107,6 +213,74 @@ enum gpuinfo_dynamic_info_valid {
gpuinfo_power_draw_max_valid,
gpuinfo_effective_load_rate_valid,
gpuinfo_multi_instance_mode_valid,
+ gpuinfo_aicpu_clock_speed_valid,
+ gpuinfo_aicpu_clock_speed_max_valid,
+ gpuinfo_aicpu_util_rate_valid,
+ gpuinfo_ctrlcpu_util_rate_valid,
+ gpuinfo_vector_util_rate_valid,
+ gpuinfo_aicube_util_rate_valid,
+ gpuinfo_npu_util_rate_valid,
+ gpuinfo_mem_bandwidth_util_rate_valid,
+ gpuinfo_mem_temp_valid,
+ gpuinfo_voltage_valid,
+ gpuinfo_health_valid,
+ gpuinfo_driver_health_valid,
+ gpuinfo_boot_status_valid,
+ gpuinfo_compatibility_valid,
+ gpuinfo_network_health_valid,
+ gpuinfo_outband_channel_state_valid,
+ gpuinfo_device_share_enabled_valid,
+ gpuinfo_p2p_enabled_valid,
+ gpuinfo_cgroup_memory_limit_valid,
+ gpuinfo_cgroup_memory_usage_valid,
+ gpuinfo_cgroup_memory_max_usage_valid,
+ gpuinfo_llc_read_hit_rate_valid,
+ gpuinfo_llc_write_hit_rate_valid,
+ gpuinfo_llc_throughput_valid,
+ gpuinfo_error_codes_valid,
+ gpuinfo_driver_error_codes_valid,
+ gpuinfo_ecc_hbm_single_bit_errors_valid,
+ gpuinfo_ecc_hbm_double_bit_errors_valid,
+ gpuinfo_ecc_hbm_total_single_bit_errors_valid,
+ gpuinfo_ecc_hbm_total_double_bit_errors_valid,
+ gpuinfo_ecc_hbm_single_bit_isolated_pages_valid,
+ gpuinfo_ecc_hbm_double_bit_isolated_pages_valid,
+ gpuinfo_ecc_ddr_single_bit_errors_valid,
+ gpuinfo_ecc_ddr_double_bit_errors_valid,
+ gpuinfo_ecc_ddr_total_single_bit_errors_valid,
+ gpuinfo_ecc_ddr_total_double_bit_errors_valid,
+ gpuinfo_ecc_ddr_single_bit_isolated_pages_valid,
+ gpuinfo_ecc_ddr_double_bit_isolated_pages_valid,
+ gpuinfo_pcie_pcs_rx_error_count_valid,
+ gpuinfo_pcie_phy_lane_error_count_valid,
+ gpuinfo_pcie_symbol_unlock_error_count_valid,
+ gpuinfo_pcie_lcrc_error_count_valid,
+ gpuinfo_pcie_dcrc_error_count_valid,
+ gpuinfo_pcie_link_tx_error_count_valid,
+ gpuinfo_pcie_link_rx_error_count_valid,
+ gpuinfo_pcie_link_lcrc_error_count_valid,
+ gpuinfo_pcie_link_ecrc_error_count_valid,
+ gpuinfo_pcie_link_retry_count_valid,
+ gpuinfo_hccs_tx_bandwidth_valid,
+ gpuinfo_hccs_rx_bandwidth_valid,
+ gpuinfo_ub_link_status_valid,
+ gpuinfo_ub_tx_bandwidth_valid,
+ gpuinfo_ub_rx_bandwidth_valid,
+ gpuinfo_rdma_tx_bandwidth_valid,
+ gpuinfo_rdma_rx_bandwidth_valid,
+ gpuinfo_network_tx_packets_valid,
+ gpuinfo_network_rx_packets_valid,
+ gpuinfo_network_tx_bytes_valid,
+ gpuinfo_network_rx_bytes_valid,
+ gpuinfo_network_tx_errors_valid,
+ gpuinfo_network_rx_errors_valid,
+ gpuinfo_network_rx_fcs_errors_valid,
+ gpuinfo_device_system_time_valid,
+ gpuinfo_ecc_hbm_history_count_valid,
+ gpuinfo_ecc_ddr_history_count_valid,
+ gpuinfo_ub_port_id_valid,
+ gpuinfo_network_tc_stats_valid,
+ gpuinfo_fault_events_valid,
gpuinfo_dynamic_info_count,
};
@@ -133,6 +307,85 @@ struct gpuinfo_dynamic_info {
unsigned int power_draw; // Power usage in milliwatts
unsigned int power_draw_max; // Max power usage in milliwatts
bool multi_instance_mode; // True if the GPU is in multi-instance mode
+ unsigned int aicpu_clock_speed; // AICPU current clock speed in MHz
+ unsigned int aicpu_clock_speed_max; // AICPU maximum clock speed in MHz
+ unsigned int aicpu_util_rate; // AICPU utilization rate in %
+ unsigned int ctrlcpu_util_rate; // Control CPU utilization rate in %
+ unsigned int vector_util_rate; // VectorCore utilization rate in %
+ unsigned int aicube_util_rate; // AICube utilization rate in %
+ unsigned int npu_util_rate; // Aggregate NPU utilization rate in %
+ unsigned int mem_bandwidth_util_rate; // Memory bandwidth utilization rate in %
+ unsigned int mem_temp; // HBM/memory temperature in Celsius
+ unsigned int voltage; // Device voltage in millivolts
+ unsigned int health; // DCMI health level: 0 normal, 1 warning, 2 major, 3 critical
+ unsigned int driver_health; // DCMI driver health level
+ unsigned int boot_status; // DCMI device boot state
+ unsigned int compatibility; // DCMI driver/firmware compatibility state
+ unsigned int network_health; // DCMI network health result
+ unsigned int outband_channel_state; // DCMI out-of-band channel state
+ bool device_share_enabled; // DCMI container/device sharing flag
+ bool p2p_enabled; // DCMI flash P2P enable flag
+ unsigned long long cgroup_memory_limit; // cgroup memory limit (bytes)
+ unsigned long long cgroup_memory_usage; // cgroup memory usage (bytes)
+ unsigned long long cgroup_memory_max_usage; // cgroup peak memory usage (bytes)
+ unsigned int llc_read_hit_rate; // LLC read hit rate (%)
+ unsigned int llc_write_hit_rate; // LLC write hit rate (%)
+ unsigned int llc_throughput; // LLC throughput (KB/s)
+ unsigned int error_code_count;
+ unsigned int error_codes[GPUINFO_MAX_ERROR_CODES];
+ unsigned int driver_error_code_count;
+ unsigned int driver_error_codes[GPUINFO_MAX_ERROR_CODES];
+ unsigned int ecc_hbm_single_bit_errors;
+ unsigned int ecc_hbm_double_bit_errors;
+ unsigned int ecc_hbm_total_single_bit_errors;
+ unsigned int ecc_hbm_total_double_bit_errors;
+ unsigned int ecc_hbm_single_bit_isolated_pages;
+ unsigned int ecc_hbm_double_bit_isolated_pages;
+ unsigned int ecc_ddr_single_bit_errors;
+ unsigned int ecc_ddr_double_bit_errors;
+ unsigned int ecc_ddr_total_single_bit_errors;
+ unsigned int ecc_ddr_total_double_bit_errors;
+ unsigned int ecc_ddr_single_bit_isolated_pages;
+ unsigned int ecc_ddr_double_bit_isolated_pages;
+ unsigned int pcie_pcs_rx_error_count;
+ unsigned int pcie_phy_lane_error_count;
+ unsigned int pcie_symbol_unlock_error_count;
+ unsigned int pcie_lcrc_error_count;
+ unsigned int pcie_dcrc_error_count;
+ unsigned int pcie_link_tx_error_count;
+ unsigned int pcie_link_rx_error_count;
+ unsigned int pcie_link_lcrc_error_count;
+ unsigned int pcie_link_ecrc_error_count;
+ unsigned int pcie_link_retry_count;
+ double hccs_tx_bandwidth; // HCCS aggregate transmit bandwidth in GB/s
+ double hccs_rx_bandwidth; // HCCS aggregate receive bandwidth in GB/s
+ unsigned int ub_link_status; // DCMI UB whole-chip link state
+ double ub_tx_bandwidth; // Aggregate UB transmit bandwidth in MB/s
+ double ub_rx_bandwidth; // Aggregate UB receive bandwidth in MB/s
+ unsigned int rdma_tx_bandwidth; // RDMA transmit bandwidth in MB/s
+ unsigned int rdma_rx_bandwidth; // RDMA receive bandwidth in MB/s
+ unsigned long long network_tx_packets;
+ unsigned long long network_rx_packets;
+ unsigned long long network_tx_bytes;
+ unsigned long long network_rx_bytes;
+ unsigned long long network_tx_errors;
+ unsigned long long network_rx_errors;
+ unsigned long long network_rx_fcs_errors;
+ unsigned int device_system_time;
+ unsigned int ecc_hbm_history_count;
+ unsigned int ecc_hbm_last_error_time;
+ unsigned int ecc_ddr_history_count;
+ unsigned int ecc_ddr_last_error_time;
+ unsigned int ub_port_id;
+ unsigned long long ub_port_tx_packets;
+ unsigned long long ub_port_rx_packets;
+ unsigned long long ub_port_tx_errors;
+ unsigned long long ub_port_rx_errors;
+ unsigned long long ub_port_crc_errors;
+ unsigned long long network_tc_tx_packets;
+ unsigned long long network_tc_rx_packets;
+ unsigned int fault_event_count;
+ struct gpuinfo_fault_event fault_events[GPUINFO_MAX_FAULT_EVENTS];
unsigned char valid[(gpuinfo_dynamic_info_count + CHAR_BIT - 1) / CHAR_BIT];
};
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b485cb40..635c89b3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -56,8 +56,27 @@ endif()
if(ASCEND_SUPPORT)
target_sources(nvtop PRIVATE extract_gpuinfo_ascend.c)
- set(DCMI_LIBRARY_PATH /usr/local/Ascend/driver/lib64/driver)
- target_link_libraries(nvtop PRIVATE "${DCMI_LIBRARY_PATH}/libdcmi.so")
+ find_package(Threads REQUIRED)
+ set(ASCEND_ROOT "" CACHE PATH "Ascend toolkit/driver root (for example /usr/local/Ascend)")
+ set(ASCEND_DCMI_HINTS
+ "/usr/local/Ascend/driver/lib64/driver"
+ "/usr/local/Ascend/driver/lib64"
+ "/usr/local/Ascend/lib64")
+ if(ASCEND_ROOT)
+ list(PREPEND ASCEND_DCMI_HINTS
+ "${ASCEND_ROOT}/driver/lib64/driver"
+ "${ASCEND_ROOT}/driver/lib64"
+ "${ASCEND_ROOT}/lib64")
+ endif()
+ find_library(DCMI_LIBRARY
+ NAMES dcmi
+ HINTS ${ASCEND_DCMI_HINTS}
+ PATH_SUFFIXES driver lib64)
+ if(NOT DCMI_LIBRARY)
+ message(FATAL_ERROR "Ascend support enabled, but libdcmi.so was not found. Set ASCEND_ROOT to the Ascend installation root.")
+ endif()
+ message(STATUS "Found Ascend DCMI: ${DCMI_LIBRARY}")
+ target_link_libraries(nvtop PRIVATE "${DCMI_LIBRARY}" Threads::Threads)
endif()
if(AMDGPU_SUPPORT OR RADEON_SUPPORT OR INTEL_SUPPORT OR V3D_SUPPORT)
diff --git a/src/extract_gpuinfo_ascend.c b/src/extract_gpuinfo_ascend.c
index e8b15999..4c3f1262 100644
--- a/src/extract_gpuinfo_ascend.c
+++ b/src/extract_gpuinfo_ascend.c
@@ -15,36 +15,181 @@
*
* You should have received a copy of the GNU General Public License
* along with nvtop. If not, see .
- *
*/
+#include
+#include
+#include
+#include
+#include
+#include
#include
#include
-#include
#include
-#include
+#include
#include "ascend/dcmi_interface_api.h"
#include "list.h"
#include "nvtop/common.h"
#include "nvtop/extract_gpuinfo_common.h"
-#define KB_TO_GB (1024 * 1024)
#define DCMI_SUCCESS 0
-#define MAX_DEVICE_NUM 64
-#define MAX_PROC_NUM 32
+#define MAX_PROC_NUM 64
#define PROC_ALLOC_INC 16
+#define ASCEND_CPU_NUM_CONFIG_SIZE 16
+#define ASCEND_PROF_DATA_NUM 3
-static int last_dcmi_return_status = DCMI_SUCCESS;
-static const char *unknown_error = "unknown Ascend DCMI error";
-static const char *local_error_string = "";
+/* PCIe profiling is optional and may block inside the driver. Keep its
+ * sampling short and reuse the last value between samples. */
+#define ASCEND_PCIE_PROFILING_TIME_MS 100
+#define ASCEND_RATED_POWER_MIN_MW 150000U
+#define ASCEND_RATED_POWER_MAX_MW 600000U
+#ifndef ASCEND_PCIE_QUERY_INTERVAL_SEC
+#define ASCEND_PCIE_QUERY_INTERVAL_SEC 5
+#endif
+#ifndef ASCEND_SLOW_QUERY_INTERVAL_SEC
+#define ASCEND_SLOW_QUERY_INTERVAL_SEC 5
+#endif
+
+/* CANN ships some releases with a strong declaration for an entry point and
+ * others with a weak/optional export. Converting the address to uintptr_t
+ * avoids -Waddress for the strong form while still allowing a missing weak
+ * export to be detected at runtime. */
+#define DCMI_SYMBOL_PRESENT(symbol) ((uintptr_t)(symbol) != (uintptr_t)0)
struct gpu_info_ascend {
struct gpu_info base;
struct list_head allocate_list;
+ /* The allocation is a contiguous array, but only its first element is
+ * linked so shutdown can release the block exactly once. */
+ unsigned allocation_count;
+ int card_id;
+ int device_id;
+ int logical_id;
+ bool logical_id_valid;
+ time_t last_pcie_query;
+ unsigned pcie_rx;
+ unsigned pcie_tx;
+ bool pcie_bandwidth_valid;
+ time_t last_slow_query;
+ time_t last_extended_query;
+ unsigned power_draw_max;
+ unsigned boot_status;
+ unsigned compatibility;
+ unsigned network_health;
+ unsigned outband_channel_state;
+ bool power_draw_max_valid;
+ bool boot_status_valid;
+ bool compatibility_valid;
+ bool network_health_valid;
+ bool outband_channel_state_valid;
+ bool device_share_enabled;
+ bool device_share_enabled_valid;
+ bool p2p_enabled;
+ bool p2p_enabled_valid;
+ unsigned long long cgroup_memory_limit;
+ unsigned long long cgroup_memory_usage;
+ unsigned long long cgroup_memory_max_usage;
+ bool cgroup_memory_limit_valid;
+ bool cgroup_memory_usage_valid;
+ bool cgroup_memory_max_usage_valid;
+ unsigned llc_read_hit_rate;
+ unsigned llc_write_hit_rate;
+ unsigned llc_throughput;
+ bool llc_valid;
+ double hccs_tx_bandwidth;
+ double hccs_rx_bandwidth;
+ bool hccs_valid;
+ unsigned ub_link_status;
+ bool ub_link_status_valid;
+ double ub_tx_bandwidth;
+ double ub_rx_bandwidth;
+ bool ub_bandwidth_valid;
+ unsigned rdma_tx_bandwidth;
+ unsigned rdma_rx_bandwidth;
+ bool rdma_bandwidth_valid;
+ unsigned long long network_tx_packets;
+ unsigned long long network_rx_packets;
+ unsigned long long network_tx_bytes;
+ unsigned long long network_rx_bytes;
+ unsigned long long network_tx_errors;
+ unsigned long long network_rx_errors;
+ unsigned long long network_rx_fcs_errors;
+ bool network_stats_valid;
+ unsigned device_system_time;
+ bool device_system_time_valid;
+ unsigned ecc_hbm_history_count;
+ unsigned ecc_hbm_last_error_time;
+ unsigned ecc_ddr_history_count;
+ unsigned ecc_ddr_last_error_time;
+ bool ecc_hbm_history_valid;
+ bool ecc_ddr_history_valid;
+ unsigned ub_port_id;
+ unsigned long long ub_port_tx_packets;
+ unsigned long long ub_port_rx_packets;
+ unsigned long long ub_port_tx_errors;
+ unsigned long long ub_port_rx_errors;
+ unsigned long long ub_port_crc_errors;
+ bool ub_port_stats_valid;
+ unsigned long long network_tc_tx_packets;
+ unsigned long long network_tc_rx_packets;
+ bool network_tc_stats_valid;
+ struct gpuinfo_fault_event fault_events[GPUINFO_MAX_FAULT_EVENTS];
+ unsigned fault_event_count;
+ bool fault_events_valid;
};
+static void ascend_invalidate_slow_cache(struct gpu_info_ascend *gpu_info) {
+ gpu_info->power_draw_max_valid = false;
+ gpu_info->boot_status_valid = false;
+ gpu_info->compatibility_valid = false;
+ gpu_info->network_health_valid = false;
+ gpu_info->outband_channel_state_valid = false;
+}
+
+static void ascend_invalidate_extended_cache(struct gpu_info_ascend *gpu_info) {
+ gpu_info->device_share_enabled_valid = false;
+ gpu_info->p2p_enabled_valid = false;
+ gpu_info->cgroup_memory_limit_valid = false;
+ gpu_info->cgroup_memory_usage_valid = false;
+ gpu_info->cgroup_memory_max_usage_valid = false;
+ gpu_info->llc_valid = false;
+ gpu_info->hccs_valid = false;
+ gpu_info->ub_link_status_valid = false;
+ gpu_info->ub_bandwidth_valid = false;
+ gpu_info->rdma_bandwidth_valid = false;
+ gpu_info->network_stats_valid = false;
+ gpu_info->device_system_time_valid = false;
+ gpu_info->ecc_hbm_history_valid = false;
+ gpu_info->ecc_ddr_history_valid = false;
+ gpu_info->ub_port_stats_valid = false;
+ gpu_info->network_tc_stats_valid = false;
+ gpu_info->fault_events_valid = false;
+}
+
+static _Thread_local int last_dcmi_return_status = DCMI_SUCCESS;
+static const char *local_error_string = "";
static LIST_HEAD(allocations);
+static pthread_t ascend_worker_thread;
+static pthread_mutex_t ascend_worker_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t ascend_worker_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t ascend_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+static bool ascend_worker_started;
+static bool ascend_worker_stop;
+static char ascend_driver_version[MAX_VERSION_STRING];
+static char ascend_dcmi_version[MAX_VERSION_STRING];
+static bool ascend_driver_version_valid;
+static bool ascend_dcmi_version_valid;
+static bool ascend_use_dcmiv2;
+static bool ascend_legacy_initialized;
+
+static void ascend_read_pcie_file(const char *pdev, const char *name, unsigned *value);
+static void ascend_refresh_slow_status(struct gpu_info_ascend *gpu_info);
+static void ascend_refresh_extended_status(struct gpu_info_ascend *gpu_info);
+static void ascend_refresh_pcie_bandwidth_cache(struct gpu_info_ascend *gpu_info);
+static void *ascend_worker_main(void *arg);
+static void ascend_start_worker(void);
+static void ascend_stop_worker(void);
static bool gpuinfo_ascend_init(void);
static void gpuinfo_ascend_shutdown(void);
@@ -54,9 +199,6 @@ static void gpuinfo_ascend_populate_static_info(struct gpu_info *_gpu_info);
static void gpuinfo_ascend_refresh_dynamic_info(struct gpu_info *_gpu_info);
static void gpuinfo_ascend_get_running_processes(struct gpu_info *_gpu_info);
-static void _encode_card_device_id_to_pdev(char *pdev, int card_id, int device_id);
-static void _decode_card_device_id_from_pdev(const char *pdev, int *card_id, int *device_id);
-
struct gpu_vendor gpu_vendor_ascend = {
.init = gpuinfo_ascend_init,
.shutdown = gpuinfo_ascend_shutdown,
@@ -70,183 +212,2855 @@ struct gpu_vendor gpu_vendor_ascend = {
__attribute__((constructor)) static void init_extract_gpuinfo_ascend(void) { register_gpu_vendor(&gpu_vendor_ascend); }
-static bool gpuinfo_ascend_init(void) {
- last_dcmi_return_status = dcmi_init();
- return last_dcmi_return_status == DCMI_SUCCESS;
+static bool ascend_query_pcie(const struct gpu_info_ascend *gpu, struct dcmi_pcie_info_all *pcie_info) {
+ memset(pcie_info, 0, sizeof(*pcie_info));
+
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_pcie_info)) {
+ last_dcmi_return_status = dcmiv2_get_device_pcie_info(gpu->logical_id, pcie_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return true;
+ }
+
+ if (gpu->card_id >= 0 && gpu->device_id >= 0 && DCMI_SYMBOL_PRESENT(dcmi_get_device_pcie_info_v2)) {
+ last_dcmi_return_status = dcmi_get_device_pcie_info_v2(gpu->card_id, gpu->device_id, pcie_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return true;
+ }
+
+ /* Older DCMI releases expose the same BDF information through v1. */
+ if (gpu->card_id >= 0 && gpu->device_id >= 0 && DCMI_SYMBOL_PRESENT(dcmi_get_device_pcie_info)) {
+ struct dcmi_pcie_info legacy_info;
+ memset(&legacy_info, 0, sizeof(legacy_info));
+ last_dcmi_return_status = dcmi_get_device_pcie_info(gpu->card_id, gpu->device_id, &legacy_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ pcie_info->bdf_busid = legacy_info.bdf_busid;
+ pcie_info->bdf_deviceid = legacy_info.bdf_deviceid;
+ pcie_info->bdf_funcid = legacy_info.bdf_funcid;
+ return true;
+ }
+ }
+
+ return false;
}
-static void gpuinfo_ascend_shutdown(void) {
- local_error_string = "";
+static void ascend_set_fallback_pdev(char *pdev, size_t pdev_size, int card_id, int device_id) {
+ snprintf(pdev, pdev_size, "%d-%d", card_id, device_id);
+}
- struct gpu_info_ascend *allocated, *tmp;
- list_for_each_entry_safe(allocated, tmp, &allocations, allocate_list) {
- list_del(&allocated->allocate_list);
- free(allocated);
+static void ascend_set_device_fallback_pdev(struct gpu_info_ascend *gpu) {
+ if (gpu->logical_id_valid && (gpu->card_id < 0 || gpu->device_id < 0))
+ snprintf(gpu->base.pdev, sizeof(gpu->base.pdev), "logical-%d", gpu->logical_id);
+ else
+ ascend_set_fallback_pdev(gpu->base.pdev, sizeof(gpu->base.pdev), gpu->card_id, gpu->device_id);
+}
+
+static void ascend_set_pdev(struct gpu_info_ascend *gpu) {
+ struct dcmi_pcie_info_all pcie_info;
+ if (ascend_query_pcie(gpu, &pcie_info)) {
+ /* PCI BDF is stable across refreshes and is more useful in config files
+ * than a DCMI card/device tuple. */
+ static const char hex[] = "0123456789abcdef";
+ unsigned domain = (unsigned)(pcie_info.domain < 0 ? 0 : pcie_info.domain) & 0xffffu;
+ unsigned bus = pcie_info.bdf_busid & 0xffu;
+ unsigned device = pcie_info.bdf_deviceid & 0x1fu;
+ unsigned function = pcie_info.bdf_funcid & 0x7u;
+ if (sizeof(gpu->base.pdev) >= 13) {
+ char *pdev = gpu->base.pdev;
+ pdev[0] = hex[(domain >> 12) & 0xf];
+ pdev[1] = hex[(domain >> 8) & 0xf];
+ pdev[2] = hex[(domain >> 4) & 0xf];
+ pdev[3] = hex[domain & 0xf];
+ pdev[4] = ':';
+ pdev[5] = hex[(bus >> 4) & 0xf];
+ pdev[6] = hex[bus & 0xf];
+ pdev[7] = ':';
+ pdev[8] = hex[(device >> 4) & 0xf];
+ pdev[9] = hex[device & 0xf];
+ pdev[10] = '.';
+ pdev[11] = hex[function];
+ pdev[12] = '\0';
+ return;
+ }
+ } else {
+ ascend_set_device_fallback_pdev(gpu);
+ return;
}
+ ascend_set_device_fallback_pdev(gpu);
}
-static const char *gpuinfo_ascend_last_error_string(void) {
- return local_error_string;
+static void ascend_copy_name(char *dst, size_t dst_size, const unsigned char *src, size_t src_size) {
+ size_t len;
+ if (!dst_size || !src)
+ return;
+ len = strnlen((const char *)src, src_size);
+ if (len >= dst_size)
+ len = dst_size - 1;
+ memcpy(dst, src, len);
+ dst[len] = '\0';
}
-static bool gpuinfo_ascend_get_device_handles(struct list_head *devices, unsigned *count) {
- int num_cards;
- int card_list[MAX_CARD_NUM] = {0};
- last_dcmi_return_status = dcmi_get_card_list(&num_cards, card_list, MAX_DEVICE_NUM);
- if (last_dcmi_return_status != DCMI_SUCCESS) {
- local_error_string = "Failed to get card num";
- return false;
- } else if (num_cards == 0) {
- local_error_string = "Not found NPU(s)";
- return false;
+static bool ascend_name_is_empty(const unsigned char *name, size_t size) {
+ return !name || strnlen((const char *)name, size) == 0;
+}
+
+static unsigned long long ascend_to_bytes(unsigned long long value, unsigned long long multiplier) {
+ if (value > ULLONG_MAX / multiplier)
+ return ULLONG_MAX;
+ return value * multiplier;
+}
+
+static unsigned long long ascend_used_from_percent(unsigned long long total, unsigned percent) {
+ unsigned long long whole;
+ unsigned long long remainder;
+ if (percent > 100)
+ percent = 100;
+ whole = total / 100;
+ remainder = total % 100;
+ return whole * percent + (remainder * percent) / 100;
+}
+
+static unsigned ascend_memory_percent(unsigned long long used, unsigned long long total) {
+ if (total == 0)
+ return 0;
+ if (used >= total)
+ return 100;
+#if defined(__SIZEOF_INT128__)
+ return (unsigned)(((__uint128_t)used * 100u) / total);
+#else
+ return (unsigned)((used / total) * 100u);
+#endif
+}
+
+static bool ascend_percentage_is_valid(unsigned value) { return value <= 100; }
+
+static bool ascend_voltage_is_valid(unsigned voltage) {
+ /* CANN uses 0x7ffd..0x7fff as the "not available" voltage range. */
+ return voltage < 0x7ffdu || voltage > 0x7fffu;
+}
+
+static bool ascend_has_legacy_ids(const struct gpu_info_ascend *gpu) {
+ return gpu && gpu->card_id >= 0 && gpu->device_id >= 0;
+}
+
+static int ascend_get_hbm_info(const struct gpu_info_ascend *gpu, struct dcmi_hbm_info *info) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_hbm_info)) {
+ last_dcmi_return_status = dcmiv2_get_device_hbm_info(gpu->logical_id, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
}
+ if (ascend_has_legacy_ids(gpu) && DCMI_SYMBOL_PRESENT(dcmi_get_device_hbm_info))
+ return (last_dcmi_return_status = dcmi_get_device_hbm_info(gpu->card_id, gpu->device_id, info));
+ return -1;
+}
- int num_devices = 0;
- int card_device_list[num_cards];
- for (int i = 0; i < num_cards; ++i) {
- int num_card_devices;
- last_dcmi_return_status = dcmi_get_device_num_in_card(card_list[i], &num_card_devices);
- if (last_dcmi_return_status != DCMI_SUCCESS) {
- local_error_string = "Failed to get device num of card";
- return false;
+static int ascend_get_legacy_hbm_info(const struct gpu_info_ascend *gpu, struct dsmi_hbm_info_stru *info) {
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_hbm_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_hbm_info(gpu->card_id, gpu->device_id, info));
+}
+
+static int ascend_get_memory_info_v3(const struct gpu_info_ascend *gpu, struct dcmi_get_memory_info_stru *info) {
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_memory_info_v3))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_memory_info_v3(gpu->card_id, gpu->device_id, info));
+}
+
+static int ascend_get_memory_info_v2(const struct gpu_info_ascend *gpu, struct dcmi_memory_info *info) {
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_memory_info_v2))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_memory_info_v2(gpu->card_id, gpu->device_id, info));
+}
+
+static int ascend_get_memory_info_v1(const struct gpu_info_ascend *gpu, struct dcmi_memory_info_stru *info) {
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_memory_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_memory_info(gpu->card_id, gpu->device_id, info));
+}
+
+static int ascend_get_utilization(const struct gpu_info_ascend *gpu, int type, unsigned *value) {
+ if (!value)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_utilization_rate)) {
+ last_dcmi_return_status = dcmiv2_get_device_utilization_rate(gpu->logical_id, type, value);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_utilization_rate))
+ return -1;
+ last_dcmi_return_status = dcmi_get_device_utilization_rate(gpu->card_id, gpu->device_id, type, value);
+ return last_dcmi_return_status;
+}
+
+static int ascend_get_frequency(const struct gpu_info_ascend *gpu, enum dcmi_freq_type type, unsigned *frequency) {
+ if (!frequency)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_frequency)) {
+ last_dcmi_return_status = dcmiv2_get_device_frequency(gpu->logical_id, type, frequency);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_frequency))
+ return -1;
+ last_dcmi_return_status = dcmi_get_device_frequency(gpu->card_id, gpu->device_id, type, frequency);
+ return last_dcmi_return_status;
+}
+
+static int ascend_get_aicore_info(const struct gpu_info_ascend *gpu, struct dcmi_aicore_info *info) {
+ int status;
+ if (!gpu || !info)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_aicore_info)) {
+ status = dcmiv2_get_device_aicore_info(gpu->logical_id, info);
+ last_dcmi_return_status = status;
+ if (status == DCMI_SUCCESS)
+ return status;
+ }
+ if (!ascend_has_legacy_ids(gpu))
+ return -1;
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_aicore_info)) {
+ status = dcmi_get_device_aicore_info(gpu->card_id, gpu->device_id, info);
+ last_dcmi_return_status = status;
+ if (status == DCMI_SUCCESS)
+ return status;
+ }
+ if (!DCMI_SYMBOL_PRESENT(dcmi_get_aicore_info))
+ return -1;
+
+ struct dsmi_aicore_info_stru legacy_info;
+ memset(&legacy_info, 0, sizeof(legacy_info));
+ status = dcmi_get_aicore_info(gpu->card_id, gpu->device_id, &legacy_info);
+ last_dcmi_return_status = status;
+ if (status == DCMI_SUCCESS) {
+ info->freq = legacy_info.freq;
+ info->cur_freq = legacy_info.curfreq;
+ }
+ return status;
+}
+
+static int ascend_get_aicpu_info(const struct gpu_info_ascend *gpu, struct dcmi_aicpu_info *info) {
+ int status;
+ if (!gpu || !info)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_aicpu_info)) {
+ status = dcmiv2_get_device_aicpu_info(gpu->logical_id, info);
+ last_dcmi_return_status = status;
+ if (status == DCMI_SUCCESS)
+ return status;
+ }
+ if (!ascend_has_legacy_ids(gpu))
+ return -1;
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_aicpu_info)) {
+ status = dcmi_get_device_aicpu_info(gpu->card_id, gpu->device_id, info);
+ last_dcmi_return_status = status;
+ if (status == DCMI_SUCCESS)
+ return status;
+ }
+ if (!DCMI_SYMBOL_PRESENT(dcmi_get_aicpu_info))
+ return -1;
+
+ struct dsmi_aicpu_info_stru legacy_info;
+ memset(&legacy_info, 0, sizeof(legacy_info));
+ status = dcmi_get_aicpu_info(gpu->card_id, gpu->device_id, &legacy_info);
+ last_dcmi_return_status = status;
+ if (status == DCMI_SUCCESS) {
+ info->max_freq = legacy_info.maxFreq;
+ info->cur_freq = legacy_info.curFreq;
+ info->aicpu_num = legacy_info.aicpuNum;
+ for (unsigned i = 0; i < MAX_CORE_NUM; ++i)
+ info->util_rate[i] = legacy_info.utilRate[i];
+ }
+ return status;
+}
+
+static int ascend_get_multi_utilization(const struct gpu_info_ascend *gpu, struct dcmi_multi_utilization_info *info) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_multi_utilization_rate)) {
+ last_dcmi_return_status = dcmiv2_get_device_multi_utilization_rate(gpu->logical_id, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_multi_utilization_rate))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_multi_utilization_rate(gpu->card_id, gpu->device_id, info));
+}
+
+static int ascend_get_ecc_info(const struct gpu_info_ascend *gpu, enum dcmi_device_type type,
+ struct dcmi_ecc_info *info) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_ecc_info)) {
+ last_dcmi_return_status = dcmiv2_get_device_ecc_info(gpu->logical_id, type, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_ecc_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_ecc_info(gpu->card_id, gpu->device_id, type, info));
+}
+
+static int ascend_get_pcie_error_info(const struct gpu_info_ascend *gpu, struct dcmi_chip_pcie_err_rate *info) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_pcie_error_cnt)) {
+ last_dcmi_return_status = dcmiv2_get_device_pcie_error_cnt(gpu->logical_id, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_pcie_error_cnt))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_pcie_error_cnt(gpu->card_id, gpu->device_id, info));
+}
+
+static int ascend_get_pcie_link_bandwidth(const struct gpu_info_ascend *gpu,
+ struct dcmi_pcie_link_bandwidth_info *info) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_pcie_link_bandwidth_info)) {
+ last_dcmi_return_status = dcmiv2_get_pcie_link_bandwidth_info(gpu->logical_id, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_pcie_link_bandwidth_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_pcie_link_bandwidth_info(gpu->card_id, gpu->device_id, info));
+}
+
+static int ascend_get_proc_mem_info(const struct gpu_info_ascend *gpu, struct dcmi_proc_mem_info *info, int *count) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_proc_mem_info)) {
+ last_dcmi_return_status = dcmiv2_get_device_proc_mem_info(gpu->logical_id, info, count);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_resource_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_resource_info(gpu->card_id, gpu->device_id, info, count));
+}
+
+static int ascend_get_chip_info_v2(const struct gpu_info_ascend *gpu, struct dcmi_chip_info_v2 *info) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_chip_info)) {
+ last_dcmi_return_status = dcmiv2_get_device_chip_info(gpu->logical_id, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_chip_info_v2))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_chip_info_v2(gpu->card_id, gpu->device_id, info));
+}
+
+static int ascend_get_chip_info(const struct gpu_info_ascend *gpu, struct dcmi_chip_info *info) {
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_chip_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_chip_info(gpu->card_id, gpu->device_id, info));
+}
+
+static int ascend_get_board_info(const struct gpu_info_ascend *gpu, struct dcmi_board_info *info) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_board_info)) {
+ last_dcmi_return_status = dcmiv2_get_device_board_info(gpu->logical_id, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_board_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_board_info(gpu->card_id, gpu->device_id, info));
+}
+
+static int ascend_get_board_id(const struct gpu_info_ascend *gpu, unsigned *board_id) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_board_id)) {
+ last_dcmi_return_status = dcmiv2_get_device_board_id(gpu->logical_id, board_id);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_board_id))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_board_id(gpu->card_id, gpu->device_id, board_id));
+}
+
+static int ascend_get_mainboard_id(const struct gpu_info_ascend *gpu, unsigned *mainboard_id) {
+ if (!mainboard_id)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_mainboard_id)) {
+ last_dcmi_return_status = dcmiv2_get_mainboard_id(gpu->logical_id, mainboard_id);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_mainboard_id))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_mainboard_id(gpu->card_id, gpu->device_id, mainboard_id));
+}
+
+static int ascend_get_ub_id_info(const struct gpu_info_ascend *gpu, struct dcmi_ub_id_info *info) {
+ if (!info || !ascend_use_dcmiv2 || !gpu->logical_id_valid || !DCMI_SYMBOL_PRESENT(dcmiv2_get_device_ub_id_info))
+ return -1;
+ return (last_dcmi_return_status = dcmiv2_get_device_ub_id_info(gpu->logical_id, info));
+}
+
+static int ascend_get_pcie_slot_id(const struct gpu_info_ascend *gpu, int *slot_id) {
+ if (!slot_id)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_pcie_slot_id)) {
+ last_dcmi_return_status = dcmiv2_get_device_pcie_slot_id(gpu->logical_id, slot_id);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_card_pcie_slot))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_card_pcie_slot(gpu->card_id, slot_id));
+}
+
+static int ascend_get_ub_slot_id(const struct gpu_info_ascend *gpu, int *slot_id) {
+ if (!slot_id || !ascend_use_dcmiv2 || !gpu->logical_id_valid || !DCMI_SYMBOL_PRESENT(dcmiv2_get_device_ub_slot_id))
+ return -1;
+ return (last_dcmi_return_status = dcmiv2_get_device_ub_slot_id(gpu->logical_id, slot_id));
+}
+
+/* The logical API returns the physical interconnect slot and chip ID as a
+ * pair. The legacy API has only the chip-position query. Its device_id is
+ * an API selector, not the out-of-band chip ID, so do not infer chip_id from
+ * it. */
+static int ascend_get_chip_location(const struct gpu_info_ascend *gpu, unsigned *chip_slot, unsigned *chip_id,
+ bool *chip_id_valid) {
+ if (!gpu || !chip_slot || !chip_id || !chip_id_valid)
+ return -1;
+ *chip_id_valid = false;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_slot_id_and_chip_id_by_dev_id)) {
+ last_dcmi_return_status = dcmiv2_get_slot_id_and_chip_id_by_dev_id(gpu->logical_id, chip_slot, chip_id);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ *chip_id_valid = true;
+ return last_dcmi_return_status;
+ }
+ }
+ if (!ascend_has_legacy_ids(gpu))
+ return -1;
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_chip_slot)) {
+ int position = -1;
+ last_dcmi_return_status = dcmi_get_device_chip_slot(gpu->card_id, gpu->device_id, &position);
+ if (last_dcmi_return_status == DCMI_SUCCESS && position >= 0) {
+ *chip_slot = (unsigned)position;
+ return last_dcmi_return_status;
}
- num_devices += num_card_devices;
- card_device_list[i] = num_card_devices;
}
+ return -1;
+}
- struct gpu_info_ascend *gpu_infos = calloc(num_devices, sizeof(*gpu_infos));
- if (!gpu_infos) {
- local_error_string = strerror(errno);
- return false;
+static int ascend_get_group_intra_id(const struct gpu_info_ascend *gpu, unsigned *group_intra_id) {
+ if (!gpu || !group_intra_id || !ascend_use_dcmiv2 || !gpu->logical_id_valid ||
+ !DCMI_SYMBOL_PRESENT(dcmiv2_get_group_intra_id_by_dev_id))
+ return -1;
+ return (last_dcmi_return_status = dcmiv2_get_group_intra_id_by_dev_id(gpu->logical_id, group_intra_id));
+}
+
+static int ascend_get_first_power_on_date(const struct gpu_info_ascend *gpu, unsigned *date) {
+ if (!gpu || !date || !ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_first_power_on_date))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_first_power_on_date(gpu->card_id, date));
+}
+
+static int ascend_get_cpu_num_config(const struct gpu_info_ascend *gpu, unsigned char *config, unsigned size) {
+ if (!gpu || !config || size < ASCEND_CPU_NUM_CONFIG_SIZE || !ascend_has_legacy_ids(gpu) ||
+ !DCMI_SYMBOL_PRESENT(dcmi_get_device_cpu_num_config))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_cpu_num_config(gpu->card_id, gpu->device_id, config, size));
+}
+
+static int ascend_get_aicpu_count_config(const struct gpu_info_ascend *gpu, unsigned char *count) {
+ if (!gpu || !count || !ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_aicpu_count_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_aicpu_count_info(gpu->card_id, gpu->device_id, count));
+}
+
+static int ascend_get_cpu_freq_mode(const struct gpu_info_ascend *gpu, int *mode) {
+ if (!gpu || !mode || !ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_cpu_freq_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_cpu_freq_info(gpu->card_id, gpu->device_id, mode));
+}
+
+static int ascend_get_p2p_enable(const struct gpu_info_ascend *gpu, int *enabled) {
+ int status;
+ if (!gpu || !enabled || !ascend_has_legacy_ids(gpu))
+ return -1;
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_p2p_enable)) {
+ status = dcmi_get_device_p2p_enable(gpu->card_id, gpu->device_id, enabled);
+ last_dcmi_return_status = status;
+ if (status == DCMI_SUCCESS)
+ return status;
}
+ if (!DCMI_SYMBOL_PRESENT(dcmi_get_p2p_enable))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_p2p_enable(gpu->card_id, gpu->device_id, enabled));
+}
- // todo: for free gpu_infos when shutting down, rewrite to direct free?
- list_add(&gpu_infos[0].allocate_list, &allocations);
+static int ascend_get_hbm_product_info(const struct gpu_info_ascend *gpu, struct dcmi_hbm_product_info *info) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_hbm_product_info)) {
+ last_dcmi_return_status = dcmiv2_get_device_hbm_product_info(gpu->logical_id, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_hbm_product_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_hbm_product_info(gpu->card_id, gpu->device_id, info));
+}
- *count = 0;
- for (int i = 0; i < num_cards; ++i) {
- for (int j = 0; j < card_device_list[i]; ++j) {
- gpu_infos[*count].base.vendor = &gpu_vendor_ascend;
- _encode_card_device_id_to_pdev(gpu_infos[*count].base.pdev, i, j);
- list_add_tail(&gpu_infos[*count].base.list, devices);
- *count += 1;
+static int ascend_get_component_version(const struct gpu_info_ascend *gpu, enum dcmi_component_type component_type,
+ unsigned char *version, unsigned length) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_component_static_version)) {
+ last_dcmi_return_status =
+ dcmiv2_get_device_component_static_version(gpu->logical_id, component_type, version, length);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_component_static_version))
+ return -1;
+ return (last_dcmi_return_status =
+ dcmi_get_device_component_static_version(gpu->card_id, gpu->device_id, component_type, version, length));
+}
+
+static int ascend_get_component_count(const struct gpu_info_ascend *gpu, unsigned *count) {
+ if (!count)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_component_cnt)) {
+ last_dcmi_return_status = dcmiv2_get_device_component_cnt(gpu->logical_id, count);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_component_count))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_component_count(gpu->card_id, gpu->device_id, count));
+}
+
+static int ascend_get_component_list(const struct gpu_info_ascend *gpu, enum dcmi_component_type *components,
+ unsigned count) {
+ if (!components || count == 0)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_component_list)) {
+ last_dcmi_return_status = dcmiv2_get_device_component_list(gpu->logical_id, components, count);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_component_list))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_component_list(gpu->card_id, gpu->device_id, components, count));
+}
+
+static int ascend_get_elabel_info(const struct gpu_info_ascend *gpu, struct dcmi_elabel_info *info) {
+ if (!info)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_elabel_info)) {
+ last_dcmi_return_status = dcmiv2_get_device_elabel_info(gpu->logical_id, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_elabel_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_elabel_info(gpu->card_id, gpu->device_id, info));
+}
+
+static int ascend_get_device_share_enable(const struct gpu_info_ascend *gpu, unsigned *enabled) {
+ if (!enabled)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_share_enable)) {
+ unsigned int value = 0;
+ last_dcmi_return_status = dcmiv2_get_device_share_enable(gpu->logical_id, &value);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ *enabled = value;
+ return last_dcmi_return_status;
}
}
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_share_enable))
+ return -1;
+ int value = 0;
+ last_dcmi_return_status = dcmi_get_device_share_enable(gpu->card_id, gpu->device_id, &value);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ *enabled = (unsigned)(value != 0);
+ return last_dcmi_return_status;
+}
- return true;
+static int ascend_get_cgroup_info(const struct gpu_info_ascend *gpu, struct dcmi_cgroup_info *info) {
+ if (!info)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_cgroup_info)) {
+ last_dcmi_return_status = dcmiv2_get_device_cgroup_info(gpu->logical_id, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_cgroup_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_cgroup_info(gpu->card_id, gpu->device_id, info));
}
-static void _encode_card_device_id_to_pdev(char *pdev, int card_id, int device_id) {
- sprintf(pdev, "%d-%d", (short)card_id, (short)device_id);
+static int ascend_get_llc_perf(const struct gpu_info_ascend *gpu, struct dcmi_llc_perf *info) {
+ if (!info)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_llc_perf_para)) {
+ last_dcmi_return_status = dcmiv2_get_device_llc_perf_para(gpu->logical_id, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_llc_perf_para))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_llc_perf_para(gpu->card_id, gpu->device_id, info));
}
-static void _decode_card_device_id_from_pdev(const char *pdev, int *card_id, int *device_id) {
- sscanf(pdev, "%d-%d", card_id, device_id);
+static int ascend_get_sensor_info(const struct gpu_info_ascend *gpu, enum dcmi_manager_sensor_id sensor_id,
+ union dcmi_sensor_info *info) {
+ if (!info)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_sensor_info)) {
+ last_dcmi_return_status = dcmiv2_get_device_sensor_info(gpu->logical_id, sensor_id, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_sensor_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_sensor_info(gpu->card_id, gpu->device_id, sensor_id, info));
}
-static void gpuinfo_ascend_populate_static_info(struct gpu_info *_gpu_info) {
- struct gpu_info_ascend *gpu_info = container_of(_gpu_info, struct gpu_info_ascend, base);
- struct gpuinfo_static_info *static_info = &gpu_info->base.static_info;
- static_info->integrated_graphics = false;
- static_info->encode_decode_shared = true;
- RESET_ALL(static_info->valid);
+static int ascend_get_device_info(const struct gpu_info_ascend *gpu, enum dcmi_main_cmd main_cmd, unsigned sub_cmd,
+ void *buf, unsigned *size) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_info)) {
+ last_dcmi_return_status = dcmiv2_get_device_info(gpu->logical_id, main_cmd, sub_cmd, buf, size);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_info(gpu->card_id, gpu->device_id, main_cmd, sub_cmd, buf, size));
+}
- int card_id, device_id;
- _decode_card_device_id_from_pdev(_gpu_info->pdev, &card_id, &device_id);
+static int ascend_get_power(const struct gpu_info_ascend *gpu, int *power) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_power_info)) {
+ last_dcmi_return_status = dcmiv2_get_device_power_info(gpu->logical_id, power);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_power_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_power_info(gpu->card_id, gpu->device_id, power));
+}
- struct dcmi_chip_info *chip_info = malloc(sizeof(struct dcmi_chip_info));
- last_dcmi_return_status = dcmi_get_device_chip_info(card_id, device_id, chip_info);
- if (last_dcmi_return_status == DCMI_SUCCESS) {
- // assume Ascend only use ASCII code for chip name
- static_info->device_name[MAX_DEVICE_NAME - 1] = '\0';
- strncpy(static_info->device_name, (char*) chip_info->chip_name, MAX_DEVICE_NAME - 1);
- SET_VALID(gpuinfo_device_name_valid, static_info->valid);
+static int ascend_get_temperature(const struct gpu_info_ascend *gpu, int *temperature) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_temperature)) {
+ last_dcmi_return_status = dcmiv2_get_device_temperature(gpu->logical_id, temperature);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
}
- free(chip_info);
- // todo: it seems that other static infos are not supported by Ascend DCMI for now, will add if possible in future
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_temperature))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_temperature(gpu->card_id, gpu->device_id, temperature));
}
-static void gpuinfo_ascend_refresh_dynamic_info(struct gpu_info *_gpu_info) {
- struct gpu_info_ascend *gpu_info = container_of(_gpu_info, struct gpu_info_ascend, base);
- struct gpuinfo_dynamic_info *dynamic_info = &gpu_info->base.dynamic_info;
- RESET_ALL(dynamic_info->valid);
+static int ascend_get_voltage(const struct gpu_info_ascend *gpu, unsigned *voltage) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_voltage)) {
+ last_dcmi_return_status = dcmiv2_get_device_voltage(gpu->logical_id, voltage);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_voltage))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_voltage(gpu->card_id, gpu->device_id, voltage));
+}
- int card_id, device_id;
- _decode_card_device_id_from_pdev(_gpu_info->pdev, &card_id, &device_id);
+static int ascend_get_health(const struct gpu_info_ascend *gpu, unsigned *health) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_health)) {
+ last_dcmi_return_status = dcmiv2_get_device_health(gpu->logical_id, health);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_health))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_health(gpu->card_id, gpu->device_id, health));
+}
- unsigned aicore_freq;
- last_dcmi_return_status = dcmi_get_device_frequency(card_id, device_id, DCMI_FREQ_AICORE_CURRENT_, &aicore_freq);
- if (last_dcmi_return_status == DCMI_SUCCESS) {
- dynamic_info->gpu_clock_speed = aicore_freq;
- SET_VALID(gpuinfo_gpu_clock_speed_valid, dynamic_info->valid);
+static int ascend_get_boot_status(const struct gpu_info_ascend *gpu, enum dcmi_boot_status *status) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_boot_status)) {
+ last_dcmi_return_status = dcmiv2_get_device_boot_status(gpu->logical_id, status);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
}
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_boot_status))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_boot_status(gpu->card_id, gpu->device_id, status));
+}
- unsigned aicore_max_freq;
- last_dcmi_return_status = dcmi_get_device_frequency(card_id, device_id, DCMI_FREQ_AICORE_MAX, &aicore_max_freq);
- if (last_dcmi_return_status == DCMI_SUCCESS) {
- dynamic_info->gpu_clock_speed_max = aicore_max_freq;
- SET_VALID(gpuinfo_gpu_clock_speed_max_valid, dynamic_info->valid);
+static int ascend_get_compatibility(const struct gpu_info_ascend *gpu, enum dcmi_device_compat *compatibility) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_compatibility)) {
+ last_dcmi_return_status = dcmiv2_get_device_compatibility(gpu->logical_id, compatibility);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
}
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_compatibility))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_compatibility(gpu->card_id, gpu->device_id, compatibility));
+}
- unsigned hbm_freq;
- last_dcmi_return_status = dcmi_get_device_frequency(card_id, device_id, DCMI_FREQ_HBM, &hbm_freq);
- if (last_dcmi_return_status == DCMI_SUCCESS) {
- dynamic_info->mem_clock_speed = hbm_freq;
- SET_VALID(gpuinfo_mem_clock_speed_valid, dynamic_info->valid);
+static int ascend_get_network_health(const struct gpu_info_ascend *gpu, enum dcmi_rdfx_detect_result *result) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_network_health)) {
+ last_dcmi_return_status = dcmiv2_get_device_network_health(gpu->logical_id, result);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
}
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_network_health))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_network_health(gpu->card_id, gpu->device_id, result));
+}
- unsigned aicore_util_rate;
- last_dcmi_return_status = dcmi_get_device_utilization_rate(card_id, device_id, DCMI_UTILIZATION_RATE_AICORE, &aicore_util_rate);
- if (last_dcmi_return_status == DCMI_SUCCESS) {
- dynamic_info->gpu_util_rate = aicore_util_rate;
- SET_VALID(gpuinfo_gpu_util_rate_valid, dynamic_info->valid);
+static int ascend_get_outband_channel_state(const struct gpu_info_ascend *gpu, int *state) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_outband_channel_state)) {
+ last_dcmi_return_status = dcmiv2_get_device_outband_channel_state(gpu->logical_id, state);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
}
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_outband_channel_state))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_outband_channel_state(gpu->card_id, gpu->device_id, state));
+}
- struct dsmi_hbm_info_stru hbm_info;
- last_dcmi_return_status = dcmi_get_hbm_info(card_id, device_id, &hbm_info);
- if (last_dcmi_return_status == DCMI_SUCCESS) {
- SET_GPUINFO_DYNAMIC(dynamic_info, total_memory, hbm_info.memory_size * KB_TO_GB);
- SET_GPUINFO_DYNAMIC(dynamic_info, used_memory, hbm_info.memory_usage * KB_TO_GB);
- SET_GPUINFO_DYNAMIC(dynamic_info, free_memory, (hbm_info.memory_size - hbm_info.memory_usage) * KB_TO_GB);
- SET_GPUINFO_DYNAMIC(dynamic_info, mem_util_rate, hbm_info.memory_usage * 100 / hbm_info.memory_size);
+static int ascend_get_error_codes(const struct gpu_info_ascend *gpu, int *count, unsigned *codes, unsigned length) {
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_error_code_list)) {
+ last_dcmi_return_status = dcmiv2_get_device_error_code_list(gpu->logical_id, count, codes, length);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
}
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_errorcode_v2))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_errorcode_v2(gpu->card_id, gpu->device_id, count, codes, length));
+}
- int device_temperature;
- last_dcmi_return_status = dcmi_get_device_temperature(card_id, device_id, &device_temperature);
- if (last_dcmi_return_status == DCMI_SUCCESS) {
- dynamic_info->gpu_temp = device_temperature;
- SET_VALID(gpuinfo_gpu_temp_valid, dynamic_info->valid);
+static int ascend_get_driver_health(unsigned *health) {
+ if (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_driver_health)) {
+ last_dcmi_return_status = dcmiv2_get_driver_health(health);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
}
+ if (!DCMI_SYMBOL_PRESENT(dcmi_get_driver_health))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_driver_health(health));
+}
- int power_usage;
- last_dcmi_return_status = dcmi_get_device_power_info(card_id, device_id, &power_usage);
- if (last_dcmi_return_status == DCMI_SUCCESS) {
- dynamic_info->power_draw = power_usage * 100;
- SET_VALID(gpuinfo_power_draw_valid, dynamic_info->valid);
+static int ascend_get_driver_error_codes(int *count, unsigned *codes, unsigned length) {
+ if (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_driver_error_code_list)) {
+ last_dcmi_return_status = dcmiv2_get_driver_error_code_list(count, codes, length);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
}
+ if (!DCMI_SYMBOL_PRESENT(dcmi_get_driver_errorcode))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_driver_errorcode(count, codes, length));
}
-static void gpuinfo_ascend_get_running_processes(struct gpu_info *_gpu_info) {
- int card_id, device_id;
- _decode_card_device_id_from_pdev(_gpu_info->pdev, &card_id, &device_id);
+static int ascend_get_current_fault_events(const struct gpu_info_ascend *gpu, struct dcmi_event *events, int capacity,
+ int *count) {
+ if (!gpu || !events || capacity <= 0 || !count)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_current_fault_event)) {
+ last_dcmi_return_status = dcmiv2_get_device_current_fault_event(gpu->logical_id, events, capacity, count);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_current_fault_event))
+ return -1;
+ return (last_dcmi_return_status =
+ dcmi_get_device_current_fault_event(gpu->card_id, gpu->device_id, events, capacity, count));
+}
- struct dcmi_proc_mem_info *proc_info = malloc(MAX_PROC_NUM * sizeof(struct dcmi_proc_mem_info));
- int proc_num = 0;
- last_dcmi_return_status = dcmi_get_device_resource_info(card_id, device_id, proc_info, &proc_num);
+static int ascend_get_hccs_bandwidth(const struct gpu_info_ascend *gpu, struct dcmi_hccs_bandwidth_info *info) {
+ if (!gpu || !info || !ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_hccs_link_bandwidth_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_hccs_link_bandwidth_info(gpu->card_id, gpu->device_id, info));
+}
+
+static int ascend_get_ub_status(const struct gpu_info_ascend *gpu, struct dcmi_ub_port_link_status *status) {
+ if (!gpu || !status)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_ub_port_link_status)) {
+ last_dcmi_return_status = dcmiv2_get_ub_port_link_status(gpu->logical_id, status);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_ub_port_link_status_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_ub_port_link_status_info(gpu->card_id, gpu->device_id, status));
+}
+
+static int ascend_get_port_list(const struct gpu_info_ascend *gpu, struct dcmi_port_list_info *port_list) {
+ if (!gpu || !port_list || !ascend_use_dcmiv2 || !gpu->logical_id_valid ||
+ !DCMI_SYMBOL_PRESENT(dcmiv2_get_device_port_list_info))
+ return -1;
+ return (last_dcmi_return_status = dcmiv2_get_device_port_list_info(gpu->logical_id, port_list));
+}
+
+static int ascend_get_rdma_bandwidth(const struct gpu_info_ascend *gpu, int port_id, unsigned profiling_time,
+ struct dcmi_network_rdma_bandwidth_info *info) {
+ if (!gpu || !info)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_rdma_bandwidth_info)) {
+ last_dcmi_return_status = dcmiv2_get_rdma_bandwidth_info(gpu->logical_id, port_id, profiling_time, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_rdma_bandwidth_info))
+ return -1;
+ return (last_dcmi_return_status =
+ dcmi_get_rdma_bandwidth_info(gpu->card_id, gpu->device_id, port_id, profiling_time, info));
+}
+
+static int ascend_get_network_pkt_stats(const struct gpu_info_ascend *gpu, int port_id,
+ struct dcmi_network_pkt_stats_info *info) {
+ if (!gpu || !info)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_netdev_pkt_stats_info)) {
+ last_dcmi_return_status = dcmiv2_get_netdev_pkt_stats_info(gpu->logical_id, port_id, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_netdev_pkt_stats_info))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_netdev_pkt_stats_info(gpu->card_id, gpu->device_id, port_id, info));
+}
+
+static int ascend_get_ub_port_stats(const struct gpu_info_ascend *gpu, const struct dcmi_ub_port_info *port,
+ struct dcmi_port_pkt_stats_info *info) {
+ if (!gpu || !port || !info || !ascend_use_dcmiv2 || !gpu->logical_id_valid ||
+ !DCMI_SYMBOL_PRESENT(dcmiv2_get_port_pkt_stats_info))
+ return -1;
+ return (last_dcmi_return_status =
+ dcmiv2_get_port_pkt_stats_info(gpu->logical_id, (struct dcmi_ub_port_info *)port, info));
+}
+
+static int ascend_get_netdev_list(const struct gpu_info_ascend *gpu, struct dcmi_netdev_list_info *info) {
+ if (!gpu || !info || !ascend_use_dcmiv2 || !gpu->logical_id_valid ||
+ !DCMI_SYMBOL_PRESENT(dcmiv2_get_device_netdev_list_info))
+ return -1;
+ return (last_dcmi_return_status = dcmiv2_get_device_netdev_list_info(gpu->logical_id, info));
+}
+
+static int ascend_get_affinity_cpu(const struct gpu_info_ascend *gpu, char *buffer, int *length) {
+ if (!gpu || !buffer || !length)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_affinity_cpu_info_by_dev_id)) {
+ last_dcmi_return_status = dcmiv2_get_affinity_cpu_info_by_dev_id(gpu->logical_id, buffer, length);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_affinity_cpu_info_by_device_id))
+ return -1;
+ return (last_dcmi_return_status =
+ dcmi_get_affinity_cpu_info_by_device_id(gpu->card_id, gpu->device_id, buffer, length));
+}
+
+static int ascend_get_die_id(const struct gpu_info_ascend *gpu, enum dcmi_die_type type, struct dcmi_die_id *die_id) {
+ if (!gpu || !die_id)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_die_id)) {
+ last_dcmi_return_status = dcmiv2_get_device_die_id(gpu->logical_id, type, die_id);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_die_v2))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_die_v2(gpu->card_id, gpu->device_id, type, die_id));
+}
+
+static int ascend_get_flash_count(const struct gpu_info_ascend *gpu, unsigned *count) {
+ if (!gpu || !count)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_flash_cnt)) {
+ last_dcmi_return_status = dcmiv2_get_device_flash_cnt(gpu->logical_id, count);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_flash_count))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_device_flash_count(gpu->card_id, gpu->device_id, count));
+}
+
+static int ascend_get_flash_info(const struct gpu_info_ascend *gpu, unsigned index, struct dcmi_flash_info *info) {
+ if (!gpu || !info)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_flash_info)) {
+ last_dcmi_return_status = dcmiv2_get_device_flash_info(gpu->logical_id, index, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu))
+ return -1;
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_flash_info_v2)) {
+ last_dcmi_return_status = dcmi_get_device_flash_info_v2(gpu->card_id, gpu->device_id, index, info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!DCMI_SYMBOL_PRESENT(dcmi_get_device_flash_info))
+ return -1;
+ struct dcmi_flash_info_stru legacy_info;
+ memset(&legacy_info, 0, sizeof(legacy_info));
+ last_dcmi_return_status = dcmi_get_device_flash_info(gpu->card_id, gpu->device_id, index, &legacy_info);
if (last_dcmi_return_status == DCMI_SUCCESS) {
- _gpu_info->processes_count = proc_num;
- _gpu_info->processes_array_size = proc_num + PROC_ALLOC_INC;
- _gpu_info->processes = reallocarray(_gpu_info->processes, _gpu_info->processes_array_size, sizeof(*_gpu_info->processes));
- if (!_gpu_info->processes) {
- perror("Could not allocate memory: ");
- exit(EXIT_FAILURE);
- }
- for (int i = 0; i < proc_num; i++) {
- _gpu_info->processes[i].type = gpu_process_compute;
- _gpu_info->processes[i].pid = proc_info[i].proc_id;
- _gpu_info->processes[i].gpu_memory_usage = proc_info[i].proc_mem_usage;
- SET_VALID(gpuinfo_process_gpu_memory_usage_valid, _gpu_info->processes[i].valid);
- }
- }
- free(proc_info);
-}
\ No newline at end of file
+ info->flash_id = legacy_info.flash_id;
+ info->device_id = legacy_info.device_id;
+ info->vendor = legacy_info.vendor;
+ info->state = legacy_info.state;
+ info->size = legacy_info.size;
+ info->sector_count = legacy_info.sector_count;
+ info->manufacturer_id = legacy_info.manufacturer_id;
+ }
+ return last_dcmi_return_status;
+}
+
+static int ascend_get_vrd_version(const struct gpu_info_ascend *gpu, char *version, int length) {
+ if (!gpu || !version || length <= 0)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_vrd_version)) {
+ last_dcmi_return_status = dcmiv2_get_vrd_version(gpu->logical_id, version, length);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_vrd_version))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_vrd_version(gpu->card_id, version, length));
+}
+
+static int ascend_get_system_time(const struct gpu_info_ascend *gpu, unsigned *system_time) {
+ int status;
+ if (!gpu || !system_time)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_system_time)) {
+ status = dcmiv2_get_device_system_time(gpu->logical_id, system_time);
+ last_dcmi_return_status = status;
+ if (status == DCMI_SUCCESS)
+ return status;
+ }
+ if (!ascend_has_legacy_ids(gpu))
+ return -1;
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_system_time)) {
+ status = dcmi_get_device_system_time(gpu->card_id, gpu->device_id, system_time);
+ last_dcmi_return_status = status;
+ if (status == DCMI_SUCCESS)
+ return status;
+ }
+ if (!DCMI_SYMBOL_PRESENT(dcmi_get_system_time))
+ return -1;
+ return (last_dcmi_return_status = dcmi_get_system_time(gpu->card_id, gpu->device_id, system_time));
+}
+
+static int ascend_get_ecc_records(const struct gpu_info_ascend *gpu, struct dcmi_ecc_record_type type, unsigned *count,
+ struct dcmi_ecc_common_data *records) {
+ if (!gpu || !count || !records)
+ return -1;
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_multi_ecc_record_info)) {
+ last_dcmi_return_status = dcmiv2_get_multi_ecc_record_info(gpu->logical_id, type, count, records);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ return last_dcmi_return_status;
+ }
+ if (!ascend_has_legacy_ids(gpu) || !DCMI_SYMBOL_PRESENT(dcmi_get_multi_ecc_record_info_v2))
+ return -1;
+ return (last_dcmi_return_status =
+ dcmi_get_multi_ecc_record_info_v2(gpu->card_id, gpu->device_id, type, count, records));
+}
+
+static bool ascend_query_hbm_sensor(const struct gpu_info_ascend *gpu, int *temperature);
+
+enum ascend_memory_source {
+ ASCEND_MEMORY_NONE,
+ ASCEND_MEMORY_HBM,
+ ASCEND_MEMORY_DDR_MB,
+};
+
+struct ascend_memory_sample {
+ enum ascend_memory_source source;
+ unsigned long long total;
+ unsigned long long used;
+ unsigned long long available;
+ unsigned frequency;
+ unsigned utilization;
+ unsigned bandwidth_utilization;
+ int temperature;
+ bool has_used;
+ bool has_available;
+ bool utilization_valid;
+ bool bandwidth_utilization_valid;
+ bool temperature_valid;
+};
+
+static bool ascend_query_memory(const struct gpu_info_ascend *gpu, struct ascend_memory_sample *sample) {
+ memset(sample, 0, sizeof(*sample));
+
+ if ((ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_hbm_info)) ||
+ ascend_has_legacy_ids(gpu)) {
+ struct dcmi_hbm_info hbm_info;
+ memset(&hbm_info, 0, sizeof(hbm_info));
+ last_dcmi_return_status = ascend_get_hbm_info(gpu, &hbm_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS && hbm_info.memory_size > 0) {
+ sample->source = ASCEND_MEMORY_HBM;
+ sample->total = hbm_info.memory_size;
+ sample->used = hbm_info.memory_usage > hbm_info.memory_size ? hbm_info.memory_size : hbm_info.memory_usage;
+ sample->has_used = true;
+ sample->frequency = hbm_info.freq;
+ sample->utilization = ascend_memory_percent(sample->used, sample->total);
+ sample->utilization_valid = true;
+ sample->bandwidth_utilization = hbm_info.bandwith_util_rate;
+ sample->bandwidth_utilization_valid = ascend_percentage_is_valid(sample->bandwidth_utilization);
+ sample->temperature = hbm_info.temp;
+ sample->temperature_valid = hbm_info.temp >= 0;
+ if (!sample->temperature_valid)
+ sample->temperature_valid = ascend_query_hbm_sensor(gpu, &sample->temperature);
+ return true;
+ }
+ }
+
+ if (ascend_has_legacy_ids(gpu)) {
+ struct dsmi_hbm_info_stru hbm_info;
+ memset(&hbm_info, 0, sizeof(hbm_info));
+ last_dcmi_return_status = ascend_get_legacy_hbm_info(gpu, &hbm_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS && hbm_info.memory_size > 0) {
+ sample->source = ASCEND_MEMORY_HBM;
+ sample->total = hbm_info.memory_size;
+ sample->used = hbm_info.memory_usage > hbm_info.memory_size ? hbm_info.memory_size : hbm_info.memory_usage;
+ sample->has_used = true;
+ sample->frequency = hbm_info.freq;
+ sample->utilization = ascend_memory_percent(sample->used, sample->total);
+ sample->utilization_valid = true;
+ sample->bandwidth_utilization = hbm_info.bandwith_util_rate;
+ sample->bandwidth_utilization_valid = ascend_percentage_is_valid(sample->bandwidth_utilization);
+ sample->temperature = hbm_info.temp;
+ sample->temperature_valid = hbm_info.temp >= 0;
+ if (!sample->temperature_valid)
+ sample->temperature_valid = ascend_query_hbm_sensor(gpu, &sample->temperature);
+ return true;
+ }
+ }
+
+ /* V3 exposes the exact available DDR amount, including huge pages. Prefer
+ * it over reconstructing used memory from a rounded percentage. */
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_memory_info_v3)) {
+ struct dcmi_get_memory_info_stru memory_info;
+ memset(&memory_info, 0, sizeof(memory_info));
+ last_dcmi_return_status = ascend_get_memory_info_v3(gpu, &memory_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS && memory_info.memory_size > 0) {
+ sample->source = ASCEND_MEMORY_DDR_MB;
+ sample->total = memory_info.memory_size;
+ bool available_valid =
+ memory_info.memory_available <= memory_info.memory_size && ascend_percentage_is_valid(memory_info.utiliza);
+ if (available_valid) {
+ sample->available = memory_info.memory_available;
+ sample->used = memory_info.memory_size - sample->available;
+ sample->has_used = true;
+ sample->has_available = true;
+ }
+ sample->frequency = memory_info.freq;
+ sample->utilization = memory_info.utiliza;
+ sample->utilization_valid = ascend_percentage_is_valid(memory_info.utiliza);
+ return true;
+ }
+ }
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_memory_info_v2)) {
+ struct dcmi_memory_info memory_info;
+ memset(&memory_info, 0, sizeof(memory_info));
+ last_dcmi_return_status = ascend_get_memory_info_v2(gpu, &memory_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS && memory_info.memory_size > 0) {
+ sample->source = ASCEND_MEMORY_DDR_MB;
+ sample->total = memory_info.memory_size;
+ sample->frequency = memory_info.freq;
+ sample->utilization = memory_info.utiliza;
+ sample->utilization_valid = ascend_percentage_is_valid(memory_info.utiliza);
+ if (sample->utilization_valid) {
+ sample->used = ascend_used_from_percent(memory_info.memory_size, memory_info.utiliza);
+ sample->available = sample->total - sample->used;
+ sample->has_used = true;
+ sample->has_available = true;
+ }
+ return true;
+ }
+ }
+
+ /* The v1 API is still present on 310P3/300i driver combinations. Its
+ * memory_size is documented in MB. */
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_memory_info)) {
+ struct dcmi_memory_info_stru memory_info;
+ memset(&memory_info, 0, sizeof(memory_info));
+ last_dcmi_return_status = ascend_get_memory_info_v1(gpu, &memory_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS && memory_info.memory_size > 0) {
+ sample->source = ASCEND_MEMORY_DDR_MB;
+ sample->total = memory_info.memory_size;
+ sample->frequency = memory_info.freq;
+ sample->utilization = memory_info.utiliza;
+ sample->utilization_valid = ascend_percentage_is_valid(memory_info.utiliza);
+ if (sample->utilization_valid) {
+ sample->used = ascend_used_from_percent(memory_info.memory_size, memory_info.utiliza);
+ sample->available = sample->total - sample->used;
+ sample->has_used = true;
+ sample->has_available = true;
+ }
+ return true;
+ }
+ }
+
+ sample->source = ASCEND_MEMORY_NONE;
+ return false;
+}
+
+static void ascend_set_memory_type(struct gpuinfo_static_info *static_info, const struct gpu_info_ascend *gpu) {
+ struct ascend_memory_sample sample;
+ if (!ascend_query_memory(gpu, &sample))
+ return;
+
+ if (sample.source == ASCEND_MEMORY_HBM)
+ snprintf(static_info->memory_type, sizeof(static_info->memory_type), "HBM");
+ else if (sample.source == ASCEND_MEMORY_DDR_MB)
+ snprintf(static_info->memory_type, sizeof(static_info->memory_type), "DDR");
+ else
+ return;
+ SET_VALID(gpuinfo_memory_type_valid, static_info->valid);
+}
+
+static void ascend_set_aicore_count(struct gpuinfo_static_info *static_info, unsigned count) {
+ if (!count)
+ return;
+ /* AICore is the closest common nvtop equivalent to a shader core. Keep
+ * engine_count unset: it is used for DRM process-cycle calculations, which
+ * DCMI does not expose for these processes. */
+ SET_GPUINFO_STATIC(static_info, n_shared_cores, count);
+}
+
+static void ascend_set_static_string(char *dst, size_t dst_size, const unsigned char *src, size_t src_size,
+ unsigned valid_bit, unsigned char *valid) {
+ size_t len;
+ if (!dst || !dst_size || !src)
+ return;
+ len = strnlen((const char *)src, src_size);
+ if (len == 0)
+ return;
+ if (len >= dst_size)
+ len = dst_size - 1;
+ memcpy(dst, src, len);
+ dst[len] = '\0';
+ SET_VALID(valid_bit, valid);
+}
+
+static void ascend_set_die_id_string(struct gpuinfo_static_info *static_info, const struct dcmi_die_id *die_id,
+ const char *label, bool *has_value) {
+ size_t used;
+ if (!static_info || !die_id || !label || !has_value)
+ return;
+ used = strlen(static_info->die_id);
+ if (used > 0 && used + 1 < sizeof(static_info->die_id)) {
+ static_info->die_id[used++] = ';';
+ static_info->die_id[used] = '\0';
+ }
+ if (used >= sizeof(static_info->die_id))
+ return;
+ snprintf(static_info->die_id + used, sizeof(static_info->die_id) - used, "%s=%08x:%08x:%08x:%08x:%08x", label,
+ die_id->soc_die[0], die_id->soc_die[1], die_id->soc_die[2], die_id->soc_die[3], die_id->soc_die[4]);
+ *has_value = true;
+}
+
+static void ascend_populate_die_id(struct gpuinfo_static_info *static_info, const struct gpu_info_ascend *gpu) {
+ static const enum dcmi_die_type types[] = {NDIE, VDIE, DDIE};
+ static const char *const labels[] = {"NDIE", "VDIE", "DDIE"};
+ bool has_value = false;
+ if (!static_info || !gpu)
+ return;
+ static_info->die_id[0] = '\0';
+ for (size_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) {
+ struct dcmi_die_id die_id;
+ memset(&die_id, 0, sizeof(die_id));
+ if (ascend_get_die_id(gpu, types[i], &die_id) == DCMI_SUCCESS)
+ ascend_set_die_id_string(static_info, &die_id, labels[i], &has_value);
+ }
+ if (has_value)
+ SET_VALID(gpuinfo_die_id_valid, static_info->valid);
+}
+
+static void ascend_populate_flash_inventory(struct gpuinfo_static_info *static_info,
+ const struct gpu_info_ascend *gpu) {
+ unsigned count = 0;
+ unsigned captured = 0;
+ if (!static_info || !gpu || ascend_get_flash_count(gpu, &count) != DCMI_SUCCESS)
+ return;
+ static_info->flash_count = count;
+ if (count > GPUINFO_MAX_FLASHES)
+ count = GPUINFO_MAX_FLASHES;
+ for (unsigned i = 0; i < count; ++i) {
+ struct dcmi_flash_info flash_info;
+ memset(&flash_info, 0, sizeof(flash_info));
+ if (ascend_get_flash_info(gpu, i, &flash_info) != DCMI_SUCCESS)
+ continue;
+ static_info->flashes[captured].flash_id = flash_info.flash_id;
+ static_info->flashes[captured].device_id = flash_info.device_id;
+ static_info->flashes[captured].vendor = flash_info.vendor;
+ static_info->flashes[captured].state = flash_info.state;
+ static_info->flashes[captured].size = flash_info.size;
+ static_info->flashes[captured].sector_count = flash_info.sector_count;
+ static_info->flashes[captured].manufacturer_id = flash_info.manufacturer_id;
+ ++captured;
+ }
+ static_info->flash_inventory_count = captured;
+ SET_VALID(gpuinfo_flash_inventory_valid, static_info->valid);
+}
+
+static void ascend_populate_netdevs(struct gpuinfo_static_info *static_info, const struct gpu_info_ascend *gpu) {
+ struct dcmi_netdev_list_info netdev_list;
+ unsigned count;
+ if (!static_info || !gpu || ascend_get_netdev_list(gpu, &netdev_list) != DCMI_SUCCESS)
+ return;
+ if (netdev_list.netdev_nums < 0)
+ return;
+ count = (unsigned)netdev_list.netdev_nums;
+ static_info->netdev_count = count;
+ if (count > GPUINFO_MAX_NETDEVS)
+ count = GPUINFO_MAX_NETDEVS;
+ for (unsigned i = 0; i < count; ++i) {
+ ascend_copy_name(static_info->netdev_names[i], sizeof(static_info->netdev_names[i]),
+ (const unsigned char *)netdev_list.netdev_name[i], NETDEV_NAME_MAX_LEN);
+ }
+ SET_VALID(gpuinfo_netdev_names_valid, static_info->valid);
+}
+
+static void ascend_populate_vrd_and_affinity(struct gpuinfo_static_info *static_info,
+ const struct gpu_info_ascend *gpu) {
+ char buffer[MAX_VERSION_STRING];
+ int length;
+ if (!static_info || !gpu)
+ return;
+ memset(buffer, 0, sizeof(buffer));
+ if (ascend_get_vrd_version(gpu, buffer, (int)sizeof(buffer)) == DCMI_SUCCESS && buffer[0] != '\0') {
+ ascend_copy_name(static_info->vrd_version, sizeof(static_info->vrd_version), (const unsigned char *)buffer,
+ sizeof(buffer));
+ SET_VALID(gpuinfo_vrd_version_valid, static_info->valid);
+ }
+ memset(buffer, 0, sizeof(buffer));
+ length = (int)sizeof(buffer);
+ if (ascend_get_affinity_cpu(gpu, buffer, &length) == DCMI_SUCCESS && buffer[0] != '\0') {
+ ascend_copy_name(static_info->affinity_cpu, sizeof(static_info->affinity_cpu), (const unsigned char *)buffer,
+ sizeof(buffer));
+ SET_VALID(gpuinfo_affinity_cpu_valid, static_info->valid);
+ }
+}
+
+static bool ascend_query_utilization(const struct gpu_info_ascend *gpu, int type, unsigned *value) {
+ unsigned utilization = 0;
+ if (!value)
+ return false;
+ last_dcmi_return_status = ascend_get_utilization(gpu, type, &utilization);
+ if (last_dcmi_return_status != DCMI_SUCCESS || !ascend_percentage_is_valid(utilization))
+ return false;
+ *value = utilization;
+ return true;
+}
+
+static void ascend_set_ecc_info(struct gpuinfo_dynamic_info *dynamic_info, enum dcmi_device_type type,
+ const struct dcmi_ecc_info *ecc_info) {
+ bool hbm = type == DCMI_DEVICE_TYPE_HBM;
+ if (!dynamic_info || !ecc_info)
+ return;
+ if (hbm) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, ecc_hbm_single_bit_errors, ecc_info->single_bit_error_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, ecc_hbm_double_bit_errors, ecc_info->double_bit_error_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, ecc_hbm_total_single_bit_errors, ecc_info->total_single_bit_error_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, ecc_hbm_total_double_bit_errors, ecc_info->total_double_bit_error_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, ecc_hbm_single_bit_isolated_pages, ecc_info->single_bit_isolated_pages_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, ecc_hbm_double_bit_isolated_pages, ecc_info->double_bit_isolated_pages_cnt);
+ } else {
+ SET_GPUINFO_DYNAMIC(dynamic_info, ecc_ddr_single_bit_errors, ecc_info->single_bit_error_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, ecc_ddr_double_bit_errors, ecc_info->double_bit_error_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, ecc_ddr_total_single_bit_errors, ecc_info->total_single_bit_error_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, ecc_ddr_total_double_bit_errors, ecc_info->total_double_bit_error_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, ecc_ddr_single_bit_isolated_pages, ecc_info->single_bit_isolated_pages_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, ecc_ddr_double_bit_isolated_pages, ecc_info->double_bit_isolated_pages_cnt);
+ }
+}
+
+static void ascend_refresh_ecc(struct gpu_info_ascend *gpu_info, struct gpuinfo_dynamic_info *dynamic_info) {
+ struct dcmi_ecc_info ecc_info;
+ if (!DCMI_SYMBOL_PRESENT(dcmi_get_device_ecc_info) &&
+ !(ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_ecc_info)))
+ return;
+
+ memset(&ecc_info, 0, sizeof(ecc_info));
+ last_dcmi_return_status = ascend_get_ecc_info(gpu_info, DCMI_DEVICE_TYPE_HBM, &ecc_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ ascend_set_ecc_info(dynamic_info, DCMI_DEVICE_TYPE_HBM, &ecc_info);
+
+ memset(&ecc_info, 0, sizeof(ecc_info));
+ last_dcmi_return_status = ascend_get_ecc_info(gpu_info, DCMI_DEVICE_TYPE_DDR, &ecc_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ ascend_set_ecc_info(dynamic_info, DCMI_DEVICE_TYPE_DDR, &ecc_info);
+}
+
+static void ascend_refresh_pcie_errors(struct gpu_info_ascend *gpu_info, struct gpuinfo_dynamic_info *dynamic_info) {
+ struct dcmi_chip_pcie_err_rate error_info;
+ bool got_soc_error_info = false;
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_pcie_error_cnt) ||
+ (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_pcie_error_cnt))) {
+ memset(&error_info, 0, sizeof(error_info));
+ last_dcmi_return_status = ascend_get_pcie_error_info(gpu_info, &error_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, pcie_pcs_rx_error_count, error_info.pcs_rx_err_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, pcie_phy_lane_error_count, error_info.phy_lane_err_counter);
+ SET_GPUINFO_DYNAMIC(dynamic_info, pcie_symbol_unlock_error_count, error_info.symbol_unlock_counter);
+ SET_GPUINFO_DYNAMIC(dynamic_info, pcie_lcrc_error_count, error_info.dl_lcrc_err_num);
+ SET_GPUINFO_DYNAMIC(dynamic_info, pcie_dcrc_error_count, error_info.dl_dcrc_err_num);
+ got_soc_error_info = true;
+ }
+ }
+
+ /* 910B and newer products expose the user-facing PCIe link counters via
+ * dcmi_get_device_info. The low-level PCS counter API is separate and may
+ * legitimately return NOT_SUPPORT, so keep both representations. */
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_info) || (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_info))) {
+ struct dcmi_pcie_link_error_info link_error_info;
+ unsigned int info_size = sizeof(link_error_info);
+ memset(&link_error_info, 0, sizeof(link_error_info));
+ last_dcmi_return_status = ascend_get_device_info(gpu_info, DCMI_MAIN_CMD_PCIE, DCMI_PCIE_SUB_CMD_PCIE_ERROR_INFO,
+ &link_error_info, &info_size);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, pcie_link_tx_error_count, link_error_info.tx_err_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, pcie_link_rx_error_count, link_error_info.rx_err_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, pcie_link_lcrc_error_count, link_error_info.lcrc_err_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, pcie_link_ecrc_error_count, link_error_info.ecrc_err_cnt);
+ SET_GPUINFO_DYNAMIC(dynamic_info, pcie_link_retry_count, link_error_info.retry_cnt);
+ } else if (!got_soc_error_info) {
+ /* Leave all PCIe error fields invalid when neither documented query is
+ * supported; unsupported is represented as N/A/null by the caller. */
+ return;
+ }
+ }
+}
+
+static void ascend_read_pcie_file(const char *pdev, const char *name, unsigned *value) {
+ char path[PATH_MAX];
+ FILE *file;
+ if (!pdev || !pdev[0] || strchr(pdev, ':') == NULL || !name || !value)
+ return;
+ snprintf(path, sizeof(path), "/sys/bus/pci/devices/%s/%s", pdev, name);
+ file = fopen(path, "r");
+ if (!file)
+ return;
+ if (fscanf(file, "%u", value) != 1)
+ *value = 0;
+ fclose(file);
+}
+
+static void ascend_refresh_pcie_link(struct gpu_info *gpu_info, struct gpuinfo_dynamic_info *dynamic_info) {
+ unsigned link_width = 0;
+ unsigned link_speed = 0;
+ ascend_read_pcie_file(gpu_info->pdev, "current_link_width", &link_width);
+ ascend_read_pcie_file(gpu_info->pdev, "current_link_speed", &link_speed);
+ if (link_width > 0)
+ SET_GPUINFO_DYNAMIC(dynamic_info, pcie_link_width, link_width);
+ if (link_speed > 0) {
+ unsigned generation = nvtop_pcie_gen_from_link_speed(link_speed);
+ if (generation > 0)
+ SET_GPUINFO_DYNAMIC(dynamic_info, pcie_link_gen, generation);
+ }
+}
+
+static unsigned ascend_bandwidth_to_kb_per_second(const unsigned int first[ASCEND_PROF_DATA_NUM],
+ const unsigned int second[ASCEND_PROF_DATA_NUM],
+ const unsigned int third[ASCEND_PROF_DATA_NUM]) {
+ /* The DCMI arrays are [min, max, average], and report MiB/ms after the
+ * driver's bytes/us -> MiB/ms conversion. Sum the average components
+ * before converting to nvtop's KiB/s unit so rounding does not accumulate
+ * across PCIe traffic classes. */
+ uint64_t average =
+ (uint64_t)first[ASCEND_PROF_DATA_NUM - 1] + second[ASCEND_PROF_DATA_NUM - 1] + third[ASCEND_PROF_DATA_NUM - 1];
+ if (average > UINT64_MAX / UINT64_C(1024000))
+ return UINT_MAX;
+ average *= UINT64_C(1024000); /* 1024 KiB/MiB * 1000 ms/s */
+ return average > UINT_MAX ? UINT_MAX : (unsigned)average;
+}
+
+static void ascend_refresh_pcie_bandwidth_cache(struct gpu_info_ascend *gpu_info) {
+ time_t now;
+ bool should_query;
+
+ if (!DCMI_SYMBOL_PRESENT(dcmi_get_pcie_link_bandwidth_info) &&
+ !(ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_pcie_link_bandwidth_info)))
+ return;
+
+ now = time(NULL);
+ should_query = gpu_info->last_pcie_query == (time_t)0 || now < gpu_info->last_pcie_query ||
+ (unsigned long long)(now - gpu_info->last_pcie_query) >= ASCEND_PCIE_QUERY_INTERVAL_SEC;
+ if (should_query) {
+ gpu_info->pcie_bandwidth_valid = false;
+ struct dcmi_pcie_link_bandwidth_info bandwidth;
+ memset(&bandwidth, 0, sizeof(bandwidth));
+ bandwidth.profiling_time = ASCEND_PCIE_PROFILING_TIME_MS;
+ last_dcmi_return_status = ascend_get_pcie_link_bandwidth(gpu_info, &bandwidth);
+ gpu_info->last_pcie_query = now;
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ gpu_info->pcie_tx = ascend_bandwidth_to_kb_per_second(bandwidth.tx_p_bw, bandwidth.tx_np_bw, bandwidth.tx_cpl_bw);
+ gpu_info->pcie_rx = ascend_bandwidth_to_kb_per_second(bandwidth.rx_p_bw, bandwidth.rx_np_bw, bandwidth.rx_cpl_bw);
+ gpu_info->pcie_bandwidth_valid = true;
+ }
+ }
+}
+
+static void ascend_apply_pcie_bandwidth(const struct gpu_info_ascend *gpu_info,
+ struct gpuinfo_dynamic_info *dynamic_info) {
+ if (!gpu_info->pcie_bandwidth_valid)
+ return;
+ SET_GPUINFO_DYNAMIC(dynamic_info, pcie_rx, gpu_info->pcie_rx);
+ SET_GPUINFO_DYNAMIC(dynamic_info, pcie_tx, gpu_info->pcie_tx);
+}
+
+static void ascend_refresh_fan(struct gpu_info_ascend *gpu_info, struct gpuinfo_dynamic_info *dynamic_info) {
+ int fan_count = 0;
+ int speed = 0;
+
+ if (!ascend_has_legacy_ids(gpu_info) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_fan_count) ||
+ !DCMI_SYMBOL_PRESENT(dcmi_get_device_fan_speed) ||
+ dcmi_get_device_fan_count(gpu_info->card_id, gpu_info->device_id, &fan_count) != DCMI_SUCCESS)
+ return;
+ if (fan_count < 1)
+ return;
+ /* fan_id == 0 is the driver's average across all fans; individual fan
+ * IDs are one-based according to the DCMI contract. */
+ if (dcmi_get_device_fan_speed(gpu_info->card_id, gpu_info->device_id, 0, &speed) == DCMI_SUCCESS && speed >= 0)
+ SET_GPUINFO_DYNAMIC(dynamic_info, fan_rpm, (unsigned)speed);
+}
+
+static void ascend_refresh_dvpp(struct gpu_info_ascend *gpu_info, struct gpuinfo_dynamic_info *dynamic_info) {
+ struct dcmi_dvpp_ratio usage;
+ if (!ascend_has_legacy_ids(gpu_info) || !DCMI_SYMBOL_PRESENT(dcmi_get_device_dvpp_ratio_info))
+ return;
+ memset(&usage, 0, sizeof(usage));
+ if (dcmi_get_device_dvpp_ratio_info(gpu_info->card_id, gpu_info->device_id, &usage) != DCMI_SUCCESS)
+ return;
+
+ if (usage.venc_ratio >= 0) {
+ unsigned value = (unsigned)usage.venc_ratio;
+ if (ascend_percentage_is_valid(value))
+ SET_GPUINFO_DYNAMIC(dynamic_info, encoder_rate, value);
+ }
+ if (usage.vdec_ratio >= 0) {
+ unsigned value = (unsigned)usage.vdec_ratio;
+ if (ascend_percentage_is_valid(value))
+ SET_GPUINFO_DYNAMIC(dynamic_info, decoder_rate, value);
+ }
+}
+
+static bool ascend_boot_status_is_valid(enum dcmi_boot_status status) {
+ return status == DCMI_BOOT_STATUS_UNINIT || status == DCMI_BOOT_STATUS_BIOS || status == DCMI_BOOT_STATUS_OS ||
+ status == DCMI_BOOT_STATUS_FINISH || status == DCMI_SYSTEM_START_FINISH;
+}
+
+static bool ascend_compatibility_is_valid(enum dcmi_device_compat compatibility) {
+ return compatibility == DCMI_COMPAT_OK || compatibility == DCMI_COMPAT_NOK || compatibility == DCMI_COMPAT_UNKNOWN;
+}
+
+static bool ascend_network_health_is_valid(enum dcmi_rdfx_detect_result result) {
+ return result >= DCMI_RDFX_DETECT_OK && result <= DCMI_RDFX_DETECT_IP_SET;
+}
+
+static bool ascend_query_power_limit(const struct gpu_info_ascend *gpu, unsigned *power_limit) {
+ struct dcmi_lp_power_info power_info;
+ unsigned info_size = sizeof(power_info);
+ if (!power_limit || (!DCMI_SYMBOL_PRESENT(dcmi_get_device_info) &&
+ !(ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_info))))
+ return false;
+ memset(&power_info, 0, sizeof(power_info));
+ if (ascend_get_device_info(gpu, DCMI_MAIN_CMD_LP, DCMI_LP_SUB_CMD_GET_POWER_INFO, &power_info, &info_size) !=
+ DCMI_SUCCESS ||
+ info_size < sizeof(power_info.soc_rated_power) || power_info.soc_rated_power < ASCEND_RATED_POWER_MIN_MW ||
+ power_info.soc_rated_power > ASCEND_RATED_POWER_MAX_MW)
+ return false;
+ *power_limit = power_info.soc_rated_power;
+ return true;
+}
+
+static bool ascend_query_hbm_sensor(const struct gpu_info_ascend *gpu, int *temperature) {
+ union dcmi_sensor_info sensor_info;
+ if (!temperature || (!DCMI_SYMBOL_PRESENT(dcmi_get_device_sensor_info) &&
+ !(ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_sensor_info))))
+ return false;
+ memset(&sensor_info, 0, sizeof(sensor_info));
+ if (ascend_use_dcmiv2 && gpu->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_sensor_info)) {
+ last_dcmi_return_status = dcmiv2_get_device_sensor_info(gpu->logical_id, DCMI_HBM_TEMP_ID, &sensor_info);
+ } else if (ascend_has_legacy_ids(gpu) && DCMI_SYMBOL_PRESENT(dcmi_get_device_sensor_info)) {
+ last_dcmi_return_status = dcmi_get_device_sensor_info(gpu->card_id, gpu->device_id, DCMI_HBM_TEMP_ID, &sensor_info);
+ } else {
+ return false;
+ }
+ if (last_dcmi_return_status != DCMI_SUCCESS)
+ return false;
+ /* Older 910 firmware returns HBM temperature in the uchar union member;
+ * newer products use the documented signed-int member. Prefer the normal
+ * representation and fall back when it is outside a physical range. */
+ *temperature = sensor_info.iint;
+ if (*temperature < 0 || *temperature > 200)
+ *temperature = sensor_info.uchar;
+ return *temperature >= 0;
+}
+
+/* Boot/compatibility/network/out-of-band state are read-only, but some of
+ * these calls enter firmware or IPMI. Cache them and refresh at a low rate so
+ * a transient or slow management query cannot stall the normal sampler. */
+static void ascend_refresh_slow_status(struct gpu_info_ascend *gpu_info) {
+ time_t now = time(NULL);
+ bool should_query = gpu_info->last_slow_query == (time_t)0 || now < gpu_info->last_slow_query ||
+ (unsigned long long)(now - gpu_info->last_slow_query) >= ASCEND_SLOW_QUERY_INTERVAL_SEC;
+ if (!should_query)
+ return;
+
+ gpu_info->last_slow_query = now;
+ ascend_invalidate_slow_cache(gpu_info);
+
+ unsigned power_limit = 0;
+ if (ascend_query_power_limit(gpu_info, &power_limit)) {
+ gpu_info->power_draw_max = power_limit;
+ gpu_info->power_draw_max_valid = true;
+ }
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_boot_status) ||
+ (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_boot_status))) {
+ enum dcmi_boot_status status = DCMI_BOOT_STATUS_UNINIT;
+ if (ascend_get_boot_status(gpu_info, &status) == DCMI_SUCCESS && ascend_boot_status_is_valid(status)) {
+ gpu_info->boot_status = (unsigned)status;
+ gpu_info->boot_status_valid = true;
+ }
+ }
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_compatibility) ||
+ (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_compatibility))) {
+ enum dcmi_device_compat compatibility = DCMI_COMPAT_UNKNOWN;
+ if (ascend_get_compatibility(gpu_info, &compatibility) == DCMI_SUCCESS &&
+ ascend_compatibility_is_valid(compatibility)) {
+ gpu_info->compatibility = (unsigned)compatibility;
+ gpu_info->compatibility_valid = true;
+ }
+ }
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_network_health) ||
+ (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_network_health))) {
+ enum dcmi_rdfx_detect_result result = DCMI_RDFX_DETECT_MAX;
+ if (ascend_get_network_health(gpu_info, &result) == DCMI_SUCCESS && ascend_network_health_is_valid(result)) {
+ gpu_info->network_health = (unsigned)result;
+ gpu_info->network_health_valid = true;
+ }
+ }
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_outband_channel_state) ||
+ (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_outband_channel_state))) {
+ int state = -1;
+ if (ascend_get_outband_channel_state(gpu_info, &state) == DCMI_SUCCESS && state >= 0) {
+ gpu_info->outband_channel_state = (unsigned)state;
+ gpu_info->outband_channel_state_valid = true;
+ }
+ }
+}
+
+static void ascend_apply_slow_status(const struct gpu_info_ascend *gpu_info,
+ struct gpuinfo_dynamic_info *dynamic_info) {
+ if (gpu_info->power_draw_max_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, power_draw_max, gpu_info->power_draw_max);
+ if (gpu_info->boot_status_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, boot_status, gpu_info->boot_status);
+ if (gpu_info->compatibility_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, compatibility, gpu_info->compatibility);
+ if (gpu_info->network_health_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, network_health, gpu_info->network_health);
+ if (gpu_info->outband_channel_state_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, outband_channel_state, gpu_info->outband_channel_state);
+}
+
+static unsigned long long ascend_add_counter(unsigned long long lhs, unsigned long long rhs) {
+ return lhs > ULLONG_MAX - rhs ? ULLONG_MAX : lhs + rhs;
+}
+
+static void ascend_collect_ub_port_stats(struct gpu_info_ascend *gpu_info, const struct dcmi_ub_port_info *port) {
+ struct dcmi_port_pkt_stats_info stats;
+ unsigned long long rx_packets = 0;
+ unsigned long long tx_packets = 0;
+ unsigned long long rx_errors = 0;
+ unsigned long long tx_errors = 0;
+
+ if (!gpu_info || !port || !DCMI_SYMBOL_PRESENT(dcmiv2_get_port_pkt_stats_info))
+ return;
+ memset(&stats, 0, sizeof(stats));
+ if (ascend_get_ub_port_stats(gpu_info, port, &stats) != DCMI_SUCCESS || stats.is_uboe_port != 0)
+ return;
+
+ rx_packets = ascend_add_counter(rx_packets, stats.ub_ipv4_pkt_cnt_rx);
+ rx_packets = ascend_add_counter(rx_packets, stats.ub_ipv6_pkt_cnt_rx);
+ rx_packets = ascend_add_counter(rx_packets, stats.unic_ipv4_pkt_cnt_rx);
+ rx_packets = ascend_add_counter(rx_packets, stats.unic_ipv6_pkt_cnt_rx);
+ rx_packets = ascend_add_counter(rx_packets, stats.ub_compact_pkt_cnt_rx);
+ rx_packets = ascend_add_counter(rx_packets, stats.ub_umoc_ctph_cnt_rx);
+ rx_packets = ascend_add_counter(rx_packets, stats.ub_umoc_ntph_cnt_rx);
+ rx_packets = ascend_add_counter(rx_packets, stats.ub_mem_pkt_cnt_rx);
+ rx_packets = ascend_add_counter(rx_packets, stats.unknown_pkt_cnt_rx);
+ tx_packets = ascend_add_counter(tx_packets, stats.ub_ipv4_pkt_cnt_tx);
+ tx_packets = ascend_add_counter(tx_packets, stats.ub_ipv6_pkt_cnt_tx);
+ tx_packets = ascend_add_counter(tx_packets, stats.unic_ipv4_pkt_cnt_tx);
+ tx_packets = ascend_add_counter(tx_packets, stats.unic_ipv6_pkt_cnt_tx);
+ tx_packets = ascend_add_counter(tx_packets, stats.ub_compact_pkt_cnt_tx);
+ tx_packets = ascend_add_counter(tx_packets, stats.ub_umoc_ctph_cnt_tx);
+ tx_packets = ascend_add_counter(tx_packets, stats.ub_umoc_ntph_cnt_tx);
+ tx_packets = ascend_add_counter(tx_packets, stats.ub_mem_pkt_cnt_tx);
+ tx_packets = ascend_add_counter(tx_packets, stats.unknown_pkt_cnt_tx);
+
+ rx_errors = ascend_add_counter(rx_errors, stats.drop_ind_cnt_rx);
+ rx_errors = ascend_add_counter(rx_errors, stats.err_ind_cnt_rx);
+ rx_errors = ascend_add_counter(rx_errors, stats.route_err_cnt_rx);
+ rx_errors = ascend_add_counter(rx_errors, stats.out_err_cnt_rx);
+ rx_errors = ascend_add_counter(rx_errors, stats.length_err_cnt_rx);
+ tx_errors = ascend_add_counter(tx_errors, stats.drop_ind_cnt_tx);
+ tx_errors = ascend_add_counter(tx_errors, stats.err_ind_cnt_tx);
+ tx_errors = ascend_add_counter(tx_errors, stats.lpbk_ind_cnt_tx);
+ tx_errors = ascend_add_counter(tx_errors, stats.out_err_cnt_tx);
+ tx_errors = ascend_add_counter(tx_errors, stats.length_err_cnt_tx);
+
+ gpu_info->ub_port_id = stats.port_id;
+ gpu_info->ub_port_tx_packets = tx_packets;
+ gpu_info->ub_port_rx_packets = rx_packets;
+ gpu_info->ub_port_tx_errors = tx_errors;
+ gpu_info->ub_port_rx_errors = rx_errors;
+ gpu_info->ub_port_crc_errors = stats.crc_error_sum;
+ gpu_info->ub_port_stats_valid = true;
+}
+
+static void ascend_collect_ecc_history(struct gpu_info_ascend *gpu_info, enum dcmi_device_type module_type,
+ unsigned *record_count, unsigned *last_error_time, bool *valid) {
+ struct dcmi_ecc_record_type type = {MULTI_ECC_INFO_READ, module_type};
+ struct dcmi_ecc_common_data records[GPUINFO_MAX_ECC_RECORDS];
+ unsigned count = GPUINFO_MAX_ECC_RECORDS;
+ unsigned last = 0;
+
+ if (!gpu_info || !record_count || !last_error_time || !valid)
+ return;
+ memset(records, 0, sizeof(records));
+ if (ascend_get_ecc_records(gpu_info, type, &count, records) != DCMI_SUCCESS || count > GPUINFO_MAX_ECC_RECORDS)
+ return;
+ for (unsigned i = 0; i < count; ++i) {
+ if (records[i].timestamp > 0 && (unsigned)records[i].timestamp > last)
+ last = (unsigned)records[i].timestamp;
+ }
+ *record_count = count;
+ *last_error_time = last;
+ *valid = true;
+}
+
+static void ascend_collect_tc_stats(struct gpu_info_ascend *gpu_info) {
+ struct dcmi_tc_stat_data stats;
+ unsigned long long tx = 0;
+ unsigned long long rx = 0;
+ if (!gpu_info || !ascend_has_legacy_ids(gpu_info) || !DCMI_SYMBOL_PRESENT(dcmi_get_netdev_tc_stat_info))
+ return;
+ memset(&stats, 0, sizeof(stats));
+ if (dcmi_get_netdev_tc_stat_info(gpu_info->card_id, gpu_info->device_id, &stats) != DCMI_SUCCESS)
+ return;
+ for (unsigned i = 0; i < TC_MAX_NUM; ++i) {
+ tx = ascend_add_counter(tx, stats.tc_tx[i]);
+ rx = ascend_add_counter(rx, stats.tc_rx[i]);
+ }
+ gpu_info->network_tc_tx_packets = tx;
+ gpu_info->network_tc_rx_packets = rx;
+ gpu_info->network_tc_stats_valid = true;
+}
+
+static void ascend_refresh_extended_status(struct gpu_info_ascend *gpu_info) {
+ time_t now = time(NULL);
+ bool should_query = gpu_info->last_extended_query == (time_t)0 || now < gpu_info->last_extended_query ||
+ (unsigned long long)(now - gpu_info->last_extended_query) >= ASCEND_SLOW_QUERY_INTERVAL_SEC;
+ if (!should_query)
+ return;
+ gpu_info->last_extended_query = now;
+ ascend_invalidate_extended_cache(gpu_info);
+
+ if (ascend_has_legacy_ids(gpu_info) &&
+ (DCMI_SYMBOL_PRESENT(dcmi_get_device_p2p_enable) || DCMI_SYMBOL_PRESENT(dcmi_get_p2p_enable))) {
+ int enabled = -1;
+ if (ascend_get_p2p_enable(gpu_info, &enabled) == DCMI_SUCCESS && (enabled == 0 || enabled == 1)) {
+ gpu_info->p2p_enabled = enabled != 0;
+ gpu_info->p2p_enabled_valid = true;
+ }
+ }
+
+ if ((ascend_use_dcmiv2 && gpu_info->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_share_enable)) ||
+ (ascend_has_legacy_ids(gpu_info) && DCMI_SYMBOL_PRESENT(dcmi_get_device_share_enable))) {
+ unsigned enabled = 0;
+ if (ascend_get_device_share_enable(gpu_info, &enabled) == DCMI_SUCCESS && enabled <= 1) {
+ gpu_info->device_share_enabled = enabled != 0;
+ gpu_info->device_share_enabled_valid = true;
+ }
+ }
+
+ if ((ascend_use_dcmiv2 && gpu_info->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_cgroup_info)) ||
+ (ascend_has_legacy_ids(gpu_info) && DCMI_SYMBOL_PRESENT(dcmi_get_device_cgroup_info))) {
+ struct dcmi_cgroup_info cgroup_info;
+ memset(&cgroup_info, 0, sizeof(cgroup_info));
+ if (ascend_get_cgroup_info(gpu_info, &cgroup_info) == DCMI_SUCCESS) {
+ gpu_info->cgroup_memory_limit = (unsigned long long)cgroup_info.limit_in_bytes;
+ gpu_info->cgroup_memory_usage = (unsigned long long)cgroup_info.usage_in_bytes;
+ gpu_info->cgroup_memory_max_usage = (unsigned long long)cgroup_info.max_usage_in_bytes;
+ gpu_info->cgroup_memory_limit_valid = true;
+ gpu_info->cgroup_memory_usage_valid = true;
+ gpu_info->cgroup_memory_max_usage_valid = true;
+ }
+ }
+
+ if ((ascend_use_dcmiv2 && gpu_info->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_llc_perf_para)) ||
+ (ascend_has_legacy_ids(gpu_info) && DCMI_SYMBOL_PRESENT(dcmi_get_device_llc_perf_para))) {
+ struct dcmi_llc_perf llc_info;
+ memset(&llc_info, 0, sizeof(llc_info));
+ if (ascend_get_llc_perf(gpu_info, &llc_info) == DCMI_SUCCESS && ascend_percentage_is_valid(llc_info.rd_hit_rate) &&
+ ascend_percentage_is_valid(llc_info.wr_hit_rate)) {
+ gpu_info->llc_read_hit_rate = llc_info.rd_hit_rate;
+ gpu_info->llc_write_hit_rate = llc_info.wr_hit_rate;
+ gpu_info->llc_throughput = llc_info.throughput;
+ gpu_info->llc_valid = true;
+ }
+ }
+
+ if (ascend_has_legacy_ids(gpu_info) && DCMI_SYMBOL_PRESENT(dcmi_get_hccs_link_bandwidth_info)) {
+ struct dcmi_hccs_bandwidth_info hccs_info;
+ memset(&hccs_info, 0, sizeof(hccs_info));
+ hccs_info.profiling_time = ASCEND_PCIE_PROFILING_TIME_MS;
+ if (ascend_get_hccs_bandwidth(gpu_info, &hccs_info) == DCMI_SUCCESS && isfinite(hccs_info.total_txbw) &&
+ isfinite(hccs_info.total_rxbw) && hccs_info.total_txbw >= 0.0 && hccs_info.total_rxbw >= 0.0) {
+ gpu_info->hccs_tx_bandwidth = hccs_info.total_txbw;
+ gpu_info->hccs_rx_bandwidth = hccs_info.total_rxbw;
+ gpu_info->hccs_valid = true;
+ }
+ }
+
+ if ((ascend_use_dcmiv2 && gpu_info->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_ub_port_link_status)) ||
+ (ascend_has_legacy_ids(gpu_info) && DCMI_SYMBOL_PRESENT(dcmi_get_ub_port_link_status_info))) {
+ struct dcmi_ub_port_link_status ub_status;
+ memset(&ub_status, 0, sizeof(ub_status));
+ if (ascend_get_ub_status(gpu_info, &ub_status) == DCMI_SUCCESS &&
+ ub_status.ub_link_status <= DCMI_UB_NO_NEED_LINK) {
+ gpu_info->ub_link_status = (unsigned)ub_status.ub_link_status;
+ gpu_info->ub_link_status_valid = true;
+ }
+ }
+
+ /* UB and RDMA bandwidth calls require a port and are deliberately sampled
+ * at the same low rate as the management-plane state. Prefer the first UB
+ * port returned by the logical-device API. The legacy 950 card API rejects
+ * port 0 and accepts product-dependent ports 4/5/6/8, so probe that bounded
+ * set rather than publishing a misleading zero sample. */
+ struct dcmi_ub_port_info selected_port = {0, 0};
+ bool have_selected_port = false;
+ bool ub_bandwidth_queried = false;
+ if (ascend_use_dcmiv2 && gpu_info->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_port_list_info)) {
+ struct dcmi_port_list_info port_list;
+ memset(&port_list, 0, sizeof(port_list));
+ if (ascend_get_port_list(gpu_info, &port_list) == DCMI_SUCCESS && port_list.die_nums > 0 &&
+ port_list.die_nums <= MAX_DIE_NUMS) {
+ for (int die = 0; die < port_list.die_nums && !have_selected_port; ++die) {
+ int port_count = port_list.die_list_data[die].port_nums;
+ if (port_count < 0 || port_count > MAX_PORT_NUMS)
+ continue;
+ for (int port = 0; port < port_count; ++port) {
+ const struct port_info *candidate = &port_list.die_list_data[die].port_list_data[port];
+ if (candidate->mode == UB_MODE && candidate->port_index >= 0) {
+ selected_port.udie_id = port_list.die_list_data[die].die_index;
+ selected_port.port_id = candidate->port_index;
+ have_selected_port = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (!have_selected_port && ascend_use_dcmiv2 && gpu_info->logical_id_valid &&
+ DCMI_SYMBOL_PRESENT(dcmiv2_get_ub_realtime_bandwidth_info)) {
+ static const int logical_ports[] = {0, 4, 5, 6, 8};
+ for (size_t i = 0; i < sizeof(logical_ports) / sizeof(logical_ports[0]); ++i) {
+ selected_port.udie_id = 0;
+ selected_port.port_id = logical_ports[i];
+ struct dcmi_ub_bandwidth_info ub_bandwidth;
+ memset(&ub_bandwidth, 0, sizeof(ub_bandwidth));
+ last_dcmi_return_status = dcmiv2_get_ub_realtime_bandwidth_info(
+ gpu_info->logical_id, ASCEND_PCIE_PROFILING_TIME_MS, &selected_port, &ub_bandwidth);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ gpu_info->ub_tx_bandwidth = (double)ub_bandwidth.tx_bandwidth;
+ gpu_info->ub_rx_bandwidth = (double)ub_bandwidth.rx_bandwidth;
+ gpu_info->ub_bandwidth_valid = true;
+ ub_bandwidth_queried = true;
+ have_selected_port = true;
+ break;
+ }
+ }
+ }
+ if (have_selected_port && !ub_bandwidth_queried && ascend_use_dcmiv2 && gpu_info->logical_id_valid &&
+ DCMI_SYMBOL_PRESENT(dcmiv2_get_ub_realtime_bandwidth_info)) {
+ struct dcmi_ub_bandwidth_info ub_bandwidth;
+ memset(&ub_bandwidth, 0, sizeof(ub_bandwidth));
+ last_dcmi_return_status = dcmiv2_get_ub_realtime_bandwidth_info(gpu_info->logical_id, ASCEND_PCIE_PROFILING_TIME_MS,
+ &selected_port, &ub_bandwidth);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ gpu_info->ub_tx_bandwidth = (double)ub_bandwidth.tx_bandwidth;
+ gpu_info->ub_rx_bandwidth = (double)ub_bandwidth.rx_bandwidth;
+ gpu_info->ub_bandwidth_valid = true;
+ ub_bandwidth_queried = true;
+ }
+ }
+
+ /* If the logical-device probe is present but returns NOT_SUPPORT, retry
+ * through the physical card/device ABI when the mapping is available. A
+ * mixed-version driver can export both entry points while only one of them
+ * is implemented for a given product. */
+ if (ascend_has_legacy_ids(gpu_info) && DCMI_SYMBOL_PRESENT(dcmi_get_ub_realtime_bandwidth_info) &&
+ !ub_bandwidth_queried) {
+ static const int legacy_ports[] = {4, 5, 6, 8, 0};
+ struct dcmi_ub_port_info legacy_port = selected_port;
+ for (size_t i = 0; i < sizeof(legacy_ports) / sizeof(legacy_ports[0]); ++i) {
+ legacy_port.udie_id = 0;
+ legacy_port.port_id = legacy_ports[i];
+ struct dcmi_ub_bandwidth_info ub_bandwidth;
+ memset(&ub_bandwidth, 0, sizeof(ub_bandwidth));
+ last_dcmi_return_status = dcmi_get_ub_realtime_bandwidth_info(
+ gpu_info->card_id, gpu_info->device_id, ASCEND_PCIE_PROFILING_TIME_MS, &legacy_port, &ub_bandwidth);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ /* The legacy card API preserves the hundredths-of-MB/s representation
+ * used by its npu-smi formatter. */
+ gpu_info->ub_tx_bandwidth = (double)ub_bandwidth.tx_bandwidth / 100.0;
+ gpu_info->ub_rx_bandwidth = (double)ub_bandwidth.rx_bandwidth / 100.0;
+ gpu_info->ub_bandwidth_valid = true;
+ ub_bandwidth_queried = true;
+ selected_port = legacy_port;
+ have_selected_port = true;
+ break;
+ }
+ }
+ }
+
+ if ((ascend_use_dcmiv2 && gpu_info->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_rdma_bandwidth_info)) ||
+ (ascend_has_legacy_ids(gpu_info) && DCMI_SYMBOL_PRESENT(dcmi_get_rdma_bandwidth_info))) {
+ struct dcmi_network_rdma_bandwidth_info rdma_bandwidth;
+ memset(&rdma_bandwidth, 0, sizeof(rdma_bandwidth));
+ /* DCMI's public npu-smi path uses port 0 for the aggregate device view. */
+ if (ascend_get_rdma_bandwidth(gpu_info, 0, ASCEND_PCIE_PROFILING_TIME_MS, &rdma_bandwidth) == DCMI_SUCCESS) {
+ gpu_info->rdma_tx_bandwidth = rdma_bandwidth.tx_bandwidth;
+ gpu_info->rdma_rx_bandwidth = rdma_bandwidth.rx_bandwidth;
+ gpu_info->rdma_bandwidth_valid = true;
+ }
+ }
+
+ if ((ascend_use_dcmiv2 && gpu_info->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_netdev_pkt_stats_info)) ||
+ (ascend_has_legacy_ids(gpu_info) && DCMI_SYMBOL_PRESENT(dcmi_get_netdev_pkt_stats_info))) {
+ struct dcmi_network_pkt_stats_info packet_stats;
+ memset(&packet_stats, 0, sizeof(packet_stats));
+ if (ascend_get_network_pkt_stats(gpu_info, 0, &packet_stats) == DCMI_SUCCESS) {
+ gpu_info->network_tx_packets = packet_stats.mac_tx_total_pkt_num;
+ gpu_info->network_rx_packets = packet_stats.mac_rx_total_pkt_num;
+ gpu_info->network_tx_bytes = packet_stats.mac_tx_total_oct_num;
+ gpu_info->network_rx_bytes = packet_stats.mac_rx_total_oct_num;
+ gpu_info->network_tx_errors = packet_stats.mac_tx_bad_pkt_num;
+ gpu_info->network_rx_errors = packet_stats.mac_rx_bad_pkt_num;
+ gpu_info->network_rx_fcs_errors = packet_stats.mac_rx_fcs_err_pkt_num;
+ gpu_info->network_stats_valid = true;
+ }
+ }
+
+ if ((ascend_use_dcmiv2 && gpu_info->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_current_fault_event)) ||
+ (ascend_has_legacy_ids(gpu_info) && DCMI_SYMBOL_PRESENT(dcmi_get_device_current_fault_event))) {
+ struct dcmi_event events[GPUINFO_MAX_FAULT_EVENTS];
+ int event_count = 0;
+ memset(events, 0, sizeof(events));
+ if (ascend_get_current_fault_events(gpu_info, events, GPUINFO_MAX_FAULT_EVENTS, &event_count) == DCMI_SUCCESS &&
+ event_count >= 0) {
+ unsigned count =
+ (unsigned)event_count > GPUINFO_MAX_FAULT_EVENTS ? GPUINFO_MAX_FAULT_EVENTS : (unsigned)event_count;
+ memset(gpu_info->fault_events, 0, sizeof(gpu_info->fault_events));
+ for (unsigned i = 0; i < count; ++i) {
+ gpu_info->fault_events[i].event_id = events[i].event_t.dms_event.event_id;
+ gpu_info->fault_events[i].severity = events[i].event_t.dms_event.severity;
+ gpu_info->fault_events[i].assertion = events[i].event_t.dms_event.assertion;
+ gpu_info->fault_events[i].alarm_raised_time = events[i].event_t.dms_event.alarm_raised_time;
+ ascend_copy_name(gpu_info->fault_events[i].event_name, sizeof(gpu_info->fault_events[i].event_name),
+ (const unsigned char *)events[i].event_t.dms_event.event_name,
+ sizeof(events[i].event_t.dms_event.event_name));
+ ascend_copy_name(gpu_info->fault_events[i].additional_info, sizeof(gpu_info->fault_events[i].additional_info),
+ (const unsigned char *)events[i].event_t.dms_event.additional_info,
+ sizeof(events[i].event_t.dms_event.additional_info));
+ }
+ gpu_info->fault_event_count = count;
+ gpu_info->fault_events_valid = true;
+ }
+ }
+
+ if ((ascend_use_dcmiv2 && gpu_info->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_system_time)) ||
+ (ascend_has_legacy_ids(gpu_info) &&
+ (DCMI_SYMBOL_PRESENT(dcmi_get_device_system_time) || DCMI_SYMBOL_PRESENT(dcmi_get_system_time)))) {
+ unsigned system_time = 0;
+ if (ascend_get_system_time(gpu_info, &system_time) == DCMI_SUCCESS) {
+ gpu_info->device_system_time = system_time;
+ gpu_info->device_system_time_valid = true;
+ }
+ }
+
+ if ((ascend_use_dcmiv2 && gpu_info->logical_id_valid && DCMI_SYMBOL_PRESENT(dcmiv2_get_multi_ecc_record_info)) ||
+ (ascend_has_legacy_ids(gpu_info) && DCMI_SYMBOL_PRESENT(dcmi_get_multi_ecc_record_info_v2))) {
+ ascend_collect_ecc_history(gpu_info, DCMI_DEVICE_TYPE_HBM, &gpu_info->ecc_hbm_history_count,
+ &gpu_info->ecc_hbm_last_error_time, &gpu_info->ecc_hbm_history_valid);
+ ascend_collect_ecc_history(gpu_info, DCMI_DEVICE_TYPE_DDR, &gpu_info->ecc_ddr_history_count,
+ &gpu_info->ecc_ddr_last_error_time, &gpu_info->ecc_ddr_history_valid);
+ }
+
+ ascend_collect_tc_stats(gpu_info);
+ if (have_selected_port)
+ ascend_collect_ub_port_stats(gpu_info, &selected_port);
+}
+
+static void ascend_copy_cached_status(struct gpu_info_ascend *dst, const struct gpu_info_ascend *src) {
+#define ASCEND_COPY_CACHE_FIELD(field) dst->field = src->field
+ ASCEND_COPY_CACHE_FIELD(last_slow_query);
+ ASCEND_COPY_CACHE_FIELD(last_extended_query);
+ ASCEND_COPY_CACHE_FIELD(last_pcie_query);
+ ASCEND_COPY_CACHE_FIELD(pcie_rx);
+ ASCEND_COPY_CACHE_FIELD(pcie_tx);
+ ASCEND_COPY_CACHE_FIELD(pcie_bandwidth_valid);
+ ASCEND_COPY_CACHE_FIELD(power_draw_max);
+ ASCEND_COPY_CACHE_FIELD(boot_status);
+ ASCEND_COPY_CACHE_FIELD(compatibility);
+ ASCEND_COPY_CACHE_FIELD(network_health);
+ ASCEND_COPY_CACHE_FIELD(outband_channel_state);
+ ASCEND_COPY_CACHE_FIELD(power_draw_max_valid);
+ ASCEND_COPY_CACHE_FIELD(boot_status_valid);
+ ASCEND_COPY_CACHE_FIELD(compatibility_valid);
+ ASCEND_COPY_CACHE_FIELD(network_health_valid);
+ ASCEND_COPY_CACHE_FIELD(outband_channel_state_valid);
+ ASCEND_COPY_CACHE_FIELD(device_share_enabled);
+ ASCEND_COPY_CACHE_FIELD(device_share_enabled_valid);
+ ASCEND_COPY_CACHE_FIELD(p2p_enabled);
+ ASCEND_COPY_CACHE_FIELD(p2p_enabled_valid);
+ ASCEND_COPY_CACHE_FIELD(cgroup_memory_limit);
+ ASCEND_COPY_CACHE_FIELD(cgroup_memory_usage);
+ ASCEND_COPY_CACHE_FIELD(cgroup_memory_max_usage);
+ ASCEND_COPY_CACHE_FIELD(cgroup_memory_limit_valid);
+ ASCEND_COPY_CACHE_FIELD(cgroup_memory_usage_valid);
+ ASCEND_COPY_CACHE_FIELD(cgroup_memory_max_usage_valid);
+ ASCEND_COPY_CACHE_FIELD(llc_read_hit_rate);
+ ASCEND_COPY_CACHE_FIELD(llc_write_hit_rate);
+ ASCEND_COPY_CACHE_FIELD(llc_throughput);
+ ASCEND_COPY_CACHE_FIELD(llc_valid);
+ ASCEND_COPY_CACHE_FIELD(hccs_tx_bandwidth);
+ ASCEND_COPY_CACHE_FIELD(hccs_rx_bandwidth);
+ ASCEND_COPY_CACHE_FIELD(hccs_valid);
+ ASCEND_COPY_CACHE_FIELD(ub_link_status);
+ ASCEND_COPY_CACHE_FIELD(ub_link_status_valid);
+ ASCEND_COPY_CACHE_FIELD(ub_tx_bandwidth);
+ ASCEND_COPY_CACHE_FIELD(ub_rx_bandwidth);
+ ASCEND_COPY_CACHE_FIELD(ub_bandwidth_valid);
+ ASCEND_COPY_CACHE_FIELD(rdma_tx_bandwidth);
+ ASCEND_COPY_CACHE_FIELD(rdma_rx_bandwidth);
+ ASCEND_COPY_CACHE_FIELD(rdma_bandwidth_valid);
+ ASCEND_COPY_CACHE_FIELD(network_tx_packets);
+ ASCEND_COPY_CACHE_FIELD(network_rx_packets);
+ ASCEND_COPY_CACHE_FIELD(network_tx_bytes);
+ ASCEND_COPY_CACHE_FIELD(network_rx_bytes);
+ ASCEND_COPY_CACHE_FIELD(network_tx_errors);
+ ASCEND_COPY_CACHE_FIELD(network_rx_errors);
+ ASCEND_COPY_CACHE_FIELD(network_rx_fcs_errors);
+ ASCEND_COPY_CACHE_FIELD(network_stats_valid);
+ ASCEND_COPY_CACHE_FIELD(device_system_time);
+ ASCEND_COPY_CACHE_FIELD(device_system_time_valid);
+ ASCEND_COPY_CACHE_FIELD(ecc_hbm_history_count);
+ ASCEND_COPY_CACHE_FIELD(ecc_hbm_last_error_time);
+ ASCEND_COPY_CACHE_FIELD(ecc_ddr_history_count);
+ ASCEND_COPY_CACHE_FIELD(ecc_ddr_last_error_time);
+ ASCEND_COPY_CACHE_FIELD(ecc_hbm_history_valid);
+ ASCEND_COPY_CACHE_FIELD(ecc_ddr_history_valid);
+ ASCEND_COPY_CACHE_FIELD(ub_port_id);
+ ASCEND_COPY_CACHE_FIELD(ub_port_tx_packets);
+ ASCEND_COPY_CACHE_FIELD(ub_port_rx_packets);
+ ASCEND_COPY_CACHE_FIELD(ub_port_tx_errors);
+ ASCEND_COPY_CACHE_FIELD(ub_port_rx_errors);
+ ASCEND_COPY_CACHE_FIELD(ub_port_crc_errors);
+ ASCEND_COPY_CACHE_FIELD(ub_port_stats_valid);
+ ASCEND_COPY_CACHE_FIELD(network_tc_tx_packets);
+ ASCEND_COPY_CACHE_FIELD(network_tc_rx_packets);
+ ASCEND_COPY_CACHE_FIELD(network_tc_stats_valid);
+ memcpy(dst->fault_events, src->fault_events, sizeof(dst->fault_events));
+ ASCEND_COPY_CACHE_FIELD(fault_event_count);
+ ASCEND_COPY_CACHE_FIELD(fault_events_valid);
+#undef ASCEND_COPY_CACHE_FIELD
+}
+
+static void *ascend_worker_main(void *arg) {
+ (void)arg;
+ for (;;) {
+ struct gpu_info_ascend *snapshot[MAX_CARD_NUM];
+ size_t snapshot_count = 0;
+ pthread_mutex_lock(&ascend_worker_mutex);
+ if (ascend_worker_stop) {
+ pthread_mutex_unlock(&ascend_worker_mutex);
+ break;
+ }
+ struct gpu_info_ascend *entry;
+ list_for_each_entry(entry, &allocations, allocate_list) {
+ unsigned allocation_count = entry->allocation_count;
+ if (allocation_count == 0)
+ allocation_count = 1;
+ if (allocation_count > MAX_CARD_NUM - snapshot_count)
+ allocation_count = MAX_CARD_NUM - snapshot_count;
+ for (unsigned i = 0; i < allocation_count; ++i)
+ snapshot[snapshot_count++] = &entry[i];
+ if (snapshot_count == MAX_CARD_NUM)
+ break;
+ }
+ pthread_mutex_unlock(&ascend_worker_mutex);
+
+ for (size_t snapshot_index = 0; snapshot_index < snapshot_count; ++snapshot_index) {
+ struct gpu_info_ascend *gpu_info = snapshot[snapshot_index];
+ struct gpu_info_ascend sample = {0};
+ sample.card_id = gpu_info->card_id;
+ sample.device_id = gpu_info->device_id;
+ sample.logical_id = gpu_info->logical_id;
+ sample.logical_id_valid = gpu_info->logical_id_valid;
+ pthread_mutex_lock(&ascend_cache_mutex);
+ ascend_copy_cached_status(&sample, gpu_info);
+ pthread_mutex_unlock(&ascend_cache_mutex);
+
+ /* These calls may enter firmware, IPMI, or management sockets. They
+ * run entirely on this worker; the curses sampler only consumes the
+ * committed cache below. */
+ ascend_refresh_slow_status(&sample);
+ ascend_refresh_extended_status(&sample);
+ ascend_refresh_pcie_bandwidth_cache(&sample);
+
+ pthread_mutex_lock(&ascend_cache_mutex);
+ ascend_copy_cached_status(gpu_info, &sample);
+ pthread_mutex_unlock(&ascend_cache_mutex);
+ }
+
+ pthread_mutex_lock(&ascend_worker_mutex);
+ if (!ascend_worker_stop) {
+ struct timespec wake_at;
+ clock_gettime(CLOCK_REALTIME, &wake_at);
+ wake_at.tv_nsec += 100000000L;
+ if (wake_at.tv_nsec >= 1000000000L) {
+ wake_at.tv_sec += 1;
+ wake_at.tv_nsec -= 1000000000L;
+ }
+ (void)pthread_cond_timedwait(&ascend_worker_cond, &ascend_worker_mutex, &wake_at);
+ }
+ bool stop = ascend_worker_stop;
+ pthread_mutex_unlock(&ascend_worker_mutex);
+ if (stop)
+ break;
+ }
+ return NULL;
+}
+
+static void ascend_start_worker(void) {
+ pthread_mutex_lock(&ascend_worker_mutex);
+ ascend_worker_stop = false;
+ if (pthread_create(&ascend_worker_thread, NULL, ascend_worker_main, NULL) == 0)
+ ascend_worker_started = true;
+ else
+ ascend_worker_started = false;
+ pthread_mutex_unlock(&ascend_worker_mutex);
+}
+
+static void ascend_stop_worker(void) {
+ pthread_mutex_lock(&ascend_worker_mutex);
+ if (!ascend_worker_started) {
+ pthread_mutex_unlock(&ascend_worker_mutex);
+ return;
+ }
+ ascend_worker_stop = true;
+ pthread_cond_signal(&ascend_worker_cond);
+ pthread_mutex_unlock(&ascend_worker_mutex);
+ pthread_join(ascend_worker_thread, NULL);
+ pthread_mutex_lock(&ascend_worker_mutex);
+ ascend_worker_started = false;
+ pthread_mutex_unlock(&ascend_worker_mutex);
+}
+
+static void ascend_apply_extended_status(const struct gpu_info_ascend *gpu_info,
+ struct gpuinfo_dynamic_info *dynamic_info) {
+ if (gpu_info->p2p_enabled_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, p2p_enabled, gpu_info->p2p_enabled);
+ if (gpu_info->device_share_enabled_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, device_share_enabled, gpu_info->device_share_enabled);
+ if (gpu_info->cgroup_memory_limit_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, cgroup_memory_limit, gpu_info->cgroup_memory_limit);
+ if (gpu_info->cgroup_memory_usage_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, cgroup_memory_usage, gpu_info->cgroup_memory_usage);
+ if (gpu_info->cgroup_memory_max_usage_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, cgroup_memory_max_usage, gpu_info->cgroup_memory_max_usage);
+ if (gpu_info->llc_valid) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, llc_read_hit_rate, gpu_info->llc_read_hit_rate);
+ SET_GPUINFO_DYNAMIC(dynamic_info, llc_write_hit_rate, gpu_info->llc_write_hit_rate);
+ SET_GPUINFO_DYNAMIC(dynamic_info, llc_throughput, gpu_info->llc_throughput);
+ }
+ if (gpu_info->hccs_valid) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, hccs_tx_bandwidth, gpu_info->hccs_tx_bandwidth);
+ SET_GPUINFO_DYNAMIC(dynamic_info, hccs_rx_bandwidth, gpu_info->hccs_rx_bandwidth);
+ }
+ if (gpu_info->ub_link_status_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, ub_link_status, gpu_info->ub_link_status);
+ if (gpu_info->ub_bandwidth_valid) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, ub_tx_bandwidth, gpu_info->ub_tx_bandwidth);
+ SET_GPUINFO_DYNAMIC(dynamic_info, ub_rx_bandwidth, gpu_info->ub_rx_bandwidth);
+ }
+ if (gpu_info->rdma_bandwidth_valid) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, rdma_tx_bandwidth, gpu_info->rdma_tx_bandwidth);
+ SET_GPUINFO_DYNAMIC(dynamic_info, rdma_rx_bandwidth, gpu_info->rdma_rx_bandwidth);
+ }
+ if (gpu_info->network_stats_valid) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, network_tx_packets, gpu_info->network_tx_packets);
+ SET_GPUINFO_DYNAMIC(dynamic_info, network_rx_packets, gpu_info->network_rx_packets);
+ SET_GPUINFO_DYNAMIC(dynamic_info, network_tx_bytes, gpu_info->network_tx_bytes);
+ SET_GPUINFO_DYNAMIC(dynamic_info, network_rx_bytes, gpu_info->network_rx_bytes);
+ SET_GPUINFO_DYNAMIC(dynamic_info, network_tx_errors, gpu_info->network_tx_errors);
+ SET_GPUINFO_DYNAMIC(dynamic_info, network_rx_errors, gpu_info->network_rx_errors);
+ SET_GPUINFO_DYNAMIC(dynamic_info, network_rx_fcs_errors, gpu_info->network_rx_fcs_errors);
+ }
+ if (gpu_info->device_system_time_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, device_system_time, gpu_info->device_system_time);
+ if (gpu_info->ecc_hbm_history_valid) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, ecc_hbm_history_count, gpu_info->ecc_hbm_history_count);
+ dynamic_info->ecc_hbm_last_error_time = gpu_info->ecc_hbm_last_error_time;
+ }
+ if (gpu_info->ecc_ddr_history_valid) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, ecc_ddr_history_count, gpu_info->ecc_ddr_history_count);
+ dynamic_info->ecc_ddr_last_error_time = gpu_info->ecc_ddr_last_error_time;
+ }
+ if (gpu_info->ub_port_stats_valid) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, ub_port_id, gpu_info->ub_port_id);
+ dynamic_info->ub_port_tx_packets = gpu_info->ub_port_tx_packets;
+ dynamic_info->ub_port_rx_packets = gpu_info->ub_port_rx_packets;
+ dynamic_info->ub_port_tx_errors = gpu_info->ub_port_tx_errors;
+ dynamic_info->ub_port_rx_errors = gpu_info->ub_port_rx_errors;
+ dynamic_info->ub_port_crc_errors = gpu_info->ub_port_crc_errors;
+ }
+ if (gpu_info->network_tc_stats_valid) {
+ dynamic_info->network_tc_tx_packets = gpu_info->network_tc_tx_packets;
+ dynamic_info->network_tc_rx_packets = gpu_info->network_tc_rx_packets;
+ SET_VALID(gpuinfo_network_tc_stats_valid, dynamic_info->valid);
+ }
+ if (gpu_info->fault_events_valid) {
+ dynamic_info->fault_event_count = gpu_info->fault_event_count;
+ memcpy(dynamic_info->fault_events, gpu_info->fault_events, sizeof(dynamic_info->fault_events));
+ SET_VALID(gpuinfo_fault_events_valid, dynamic_info->valid);
+ }
+}
+
+static bool gpuinfo_ascend_init(void) {
+ local_error_string = "";
+ memset(ascend_driver_version, 0, sizeof(ascend_driver_version));
+ memset(ascend_dcmi_version, 0, sizeof(ascend_dcmi_version));
+ ascend_driver_version_valid = false;
+ ascend_dcmi_version_valid = false;
+ ascend_use_dcmiv2 = false;
+ ascend_legacy_initialized = false;
+ if (DCMI_SYMBOL_PRESENT(dcmiv2_init)) {
+ last_dcmi_return_status = dcmiv2_init();
+ ascend_use_dcmiv2 = last_dcmi_return_status == DCMI_SUCCESS;
+ }
+ if (!ascend_use_dcmiv2) {
+ last_dcmi_return_status = dcmi_init();
+ ascend_legacy_initialized = last_dcmi_return_status == DCMI_SUCCESS;
+ }
+ if (last_dcmi_return_status != DCMI_SUCCESS)
+ return false;
+
+ if (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_driver_version))
+ last_dcmi_return_status = dcmiv2_get_driver_version(ascend_driver_version, sizeof(ascend_driver_version));
+ else if (DCMI_SYMBOL_PRESENT(dcmi_get_driver_version))
+ last_dcmi_return_status = dcmi_get_driver_version(ascend_driver_version, sizeof(ascend_driver_version));
+ else
+ last_dcmi_return_status = -1;
+ ascend_driver_version_valid = last_dcmi_return_status == DCMI_SUCCESS && ascend_driver_version[0] != '\0';
+
+ if (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_dcmi_version))
+ last_dcmi_return_status = dcmiv2_get_dcmi_version(ascend_dcmi_version, sizeof(ascend_dcmi_version));
+ else if (DCMI_SYMBOL_PRESENT(dcmi_get_dcmi_version))
+ last_dcmi_return_status = dcmi_get_dcmi_version(ascend_dcmi_version, sizeof(ascend_dcmi_version));
+ else
+ last_dcmi_return_status = -1;
+ ascend_dcmi_version_valid = last_dcmi_return_status == DCMI_SUCCESS && ascend_dcmi_version[0] != '\0';
+ ascend_start_worker();
+ if (!ascend_worker_started) {
+ local_error_string = "Failed to start DCMI worker";
+ return false;
+ }
+ return true;
+}
+
+static void gpuinfo_ascend_shutdown(void) {
+ local_error_string = "";
+ ascend_stop_worker();
+ struct gpu_info_ascend *allocated, *tmp;
+ list_for_each_entry_safe(allocated, tmp, &allocations, allocate_list) {
+ list_del(&allocated->allocate_list);
+ free(allocated);
+ }
+ memset(ascend_driver_version, 0, sizeof(ascend_driver_version));
+ memset(ascend_dcmi_version, 0, sizeof(ascend_dcmi_version));
+ ascend_driver_version_valid = false;
+ ascend_dcmi_version_valid = false;
+ ascend_use_dcmiv2 = false;
+ ascend_legacy_initialized = false;
+}
+
+static const char *gpuinfo_ascend_last_error_string(void) { return local_error_string; }
+
+static bool gpuinfo_ascend_get_device_handles(struct list_head *devices, unsigned *count) {
+ int num_cards = 0;
+ int card_list[MAX_CARD_NUM] = {0};
+ int card_device_list[MAX_CARD_NUM] = {0};
+ int logical_device_list[MAX_CARD_NUM] = {0};
+ size_t num_devices = 0;
+ bool use_dcmiv2 = false;
+
+ if (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_list)) {
+ int logical_count = 0;
+ last_dcmi_return_status = dcmiv2_get_device_list(logical_device_list, &logical_count, MAX_CARD_NUM);
+ if (last_dcmi_return_status == DCMI_SUCCESS && logical_count > 0 && logical_count <= MAX_CARD_NUM) {
+ int accepted_count = 0;
+ for (int logical_index = 0; logical_index < logical_count; ++logical_index) {
+ bool keep_device = true;
+ if (DCMI_SYMBOL_PRESENT(dcmiv2_get_device_type)) {
+ enum dcmi_unit_type device_type = INVALID_TYPE;
+ int type_status = dcmiv2_get_device_type(logical_device_list[logical_index], &device_type);
+ /* A logical-device list may include MCU/CPU management devices on
+ * newer products. nvtop monitors NPU devices only; preserve an
+ * entry when type probing itself is unavailable. */
+ if (type_status == DCMI_SUCCESS && device_type != NPU_TYPE)
+ keep_device = false;
+ }
+ if (keep_device)
+ logical_device_list[accepted_count++] = logical_device_list[logical_index];
+ }
+ num_devices = (size_t)accepted_count;
+ use_dcmiv2 = accepted_count > 0;
+ if (!use_dcmiv2)
+ ascend_use_dcmiv2 = false;
+ } else {
+ /* dcmiv2_init is only implemented for some newer products. A library
+ * may export it yet report NOT_SUPPORT for the logical-device list;
+ * keep the legacy enumeration path available in that case. */
+ ascend_use_dcmiv2 = false;
+ }
+ }
+
+ if (!use_dcmiv2) {
+ if (!ascend_legacy_initialized) {
+ last_dcmi_return_status = dcmi_init();
+ if (last_dcmi_return_status != DCMI_SUCCESS) {
+ local_error_string = "Failed to initialize legacy DCMI";
+ return false;
+ }
+ ascend_legacy_initialized = true;
+ }
+ last_dcmi_return_status = dcmi_get_card_list(&num_cards, card_list, MAX_CARD_NUM);
+ if (last_dcmi_return_status != DCMI_SUCCESS || num_cards <= 0 || num_cards > MAX_CARD_NUM) {
+ local_error_string = "Failed to get card list";
+ return false;
+ }
+
+ for (int card_index = 0; card_index < num_cards; ++card_index) {
+ int device_count = 0;
+ last_dcmi_return_status = dcmi_get_device_num_in_card(card_list[card_index], &device_count);
+ if (last_dcmi_return_status != DCMI_SUCCESS || device_count < 0 || device_count > MAX_CARD_NUM) {
+ local_error_string = "Failed to get device num of card";
+ return false;
+ }
+ card_device_list[card_index] = device_count;
+ num_devices += (size_t)device_count;
+ }
+ }
+
+ if (num_devices == 0 || num_devices > UINT_MAX) {
+ local_error_string = "Not found NPU(s)";
+ return false;
+ }
+
+ struct gpu_info_ascend *gpu_infos = calloc(num_devices, sizeof(*gpu_infos));
+ if (!gpu_infos) {
+ local_error_string = strerror(errno);
+ return false;
+ }
+
+ *count = 0;
+ if (use_dcmiv2) {
+ for (int logical_index = 0; logical_index < (int)num_devices; ++logical_index) {
+ struct gpu_info_ascend *gpu_info = &gpu_infos[*count];
+ gpu_info->base.vendor = &gpu_vendor_ascend;
+ gpu_info->card_id = -1;
+ gpu_info->device_id = -1;
+ gpu_info->logical_id = logical_device_list[logical_index];
+ gpu_info->logical_id_valid = true;
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_card_id_device_id_from_logicid)) {
+ int card_id = -1;
+ int device_id = -1;
+ last_dcmi_return_status =
+ dcmi_get_card_id_device_id_from_logicid(&card_id, &device_id, (unsigned int)gpu_info->logical_id);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ gpu_info->card_id = card_id;
+ gpu_info->device_id = device_id;
+ }
+ }
+ ascend_set_pdev(gpu_info);
+ list_add_tail(&gpu_info->base.list, devices);
+ *count += 1;
+ }
+ } else {
+ for (int card_index = 0; card_index < num_cards; ++card_index) {
+ for (int device_index = 0; device_index < card_device_list[card_index]; ++device_index) {
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_type)) {
+ enum dcmi_unit_type device_type = INVALID_TYPE;
+ int type_status = dcmi_get_device_type(card_list[card_index], device_index, &device_type);
+ /* Some legacy releases report MCU/CPU management units in the
+ * per-card count. Keep unknown type probes compatible, but never
+ * expose a unit explicitly identified as non-NPU. */
+ if (type_status == DCMI_SUCCESS && device_type != NPU_TYPE)
+ continue;
+ }
+ struct gpu_info_ascend *gpu_info = &gpu_infos[*count];
+ gpu_info->base.vendor = &gpu_vendor_ascend;
+ gpu_info->card_id = card_list[card_index];
+ gpu_info->device_id = device_index;
+ gpu_info->logical_id = -1;
+ gpu_info->logical_id_valid = false;
+ ascend_set_pdev(gpu_info);
+ list_add_tail(&gpu_info->base.list, devices);
+ *count += 1;
+ }
+ }
+ }
+ if (*count == 0) {
+ free(gpu_infos);
+ local_error_string = "Not found NPU(s)";
+ return false;
+ }
+ gpu_infos[0].allocation_count = *count;
+ pthread_mutex_lock(&ascend_worker_mutex);
+ list_add(&gpu_infos[0].allocate_list, &allocations);
+ pthread_cond_signal(&ascend_worker_cond);
+ pthread_mutex_unlock(&ascend_worker_mutex);
+ return true;
+}
+
+static void gpuinfo_ascend_populate_static_info(struct gpu_info *_gpu_info) {
+ struct gpu_info_ascend *gpu_info = container_of(_gpu_info, struct gpu_info_ascend, base);
+ struct gpuinfo_static_info *static_info = &gpu_info->base.static_info;
+ bool got_chip = false;
+
+ memset(static_info, 0, sizeof(*static_info));
+ static_info->integrated_graphics = false;
+ /* DCMI reports VENC and VDEC as independent DVPP engines. */
+ static_info->encode_decode_shared = false;
+
+ if ((ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_chip_info)) ||
+ DCMI_SYMBOL_PRESENT(dcmi_get_device_chip_info_v2)) {
+ struct dcmi_chip_info_v2 chip_info;
+ memset(&chip_info, 0, sizeof(chip_info));
+ last_dcmi_return_status = ascend_get_chip_info_v2(gpu_info, &chip_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ const unsigned char *name =
+ ascend_name_is_empty(chip_info.chip_name, MAX_CHIP_NAME_LEN) ? chip_info.npu_name : chip_info.chip_name;
+ bool has_name = !ascend_name_is_empty(name, MAX_CHIP_NAME_LEN);
+ if (has_name) {
+ ascend_copy_name(static_info->device_name, sizeof(static_info->device_name), name, MAX_CHIP_NAME_LEN);
+ SET_VALID(gpuinfo_device_name_valid, static_info->valid);
+ }
+ ascend_set_static_string(static_info->chip_type, sizeof(static_info->chip_type), chip_info.chip_type,
+ MAX_CHIP_NAME_LEN, gpuinfo_chip_type_valid, static_info->valid);
+ ascend_set_static_string(static_info->chip_version, sizeof(static_info->chip_version), chip_info.chip_ver,
+ MAX_CHIP_NAME_LEN, gpuinfo_chip_version_valid, static_info->valid);
+ ascend_set_static_string(static_info->npu_name, sizeof(static_info->npu_name), chip_info.npu_name,
+ MAX_CHIP_NAME_LEN, gpuinfo_npu_name_valid, static_info->valid);
+ ascend_set_aicore_count(static_info, chip_info.aicore_cnt);
+ got_chip = has_name || chip_info.aicore_cnt > 0;
+ }
+ }
+
+ if (!got_chip) {
+ struct dcmi_chip_info chip_info;
+ memset(&chip_info, 0, sizeof(chip_info));
+ last_dcmi_return_status = ascend_get_chip_info(gpu_info, &chip_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ if (!ascend_name_is_empty(chip_info.chip_name, MAX_CHIP_NAME_LEN)) {
+ ascend_copy_name(static_info->device_name, sizeof(static_info->device_name), chip_info.chip_name,
+ MAX_CHIP_NAME_LEN);
+ SET_VALID(gpuinfo_device_name_valid, static_info->valid);
+ }
+ ascend_set_static_string(static_info->chip_type, sizeof(static_info->chip_type), chip_info.chip_type,
+ MAX_CHIP_NAME_LEN, gpuinfo_chip_type_valid, static_info->valid);
+ ascend_set_static_string(static_info->chip_version, sizeof(static_info->chip_version), chip_info.chip_ver,
+ MAX_CHIP_NAME_LEN, gpuinfo_chip_version_valid, static_info->valid);
+ ascend_set_aicore_count(static_info, chip_info.aicore_cnt);
+ }
+ }
+
+ bool got_board_info = false;
+ if ((ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_board_info)) ||
+ DCMI_SYMBOL_PRESENT(dcmi_get_device_board_info)) {
+ struct dcmi_board_info board_info;
+ memset(&board_info, 0, sizeof(board_info));
+ last_dcmi_return_status = ascend_get_board_info(gpu_info, &board_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ SET_GPUINFO_STATIC(static_info, board_id, board_info.board_id);
+ SET_GPUINFO_STATIC(static_info, pcb_id, board_info.pcb_id);
+ SET_GPUINFO_STATIC(static_info, bom_id, board_info.bom_id);
+ SET_GPUINFO_STATIC(static_info, slot_id, board_info.slot_id);
+ got_board_info = true;
+ }
+ }
+ if (!got_board_info && ((ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_board_id)) ||
+ DCMI_SYMBOL_PRESENT(dcmi_get_device_board_id))) {
+ unsigned board_id = 0;
+ last_dcmi_return_status = ascend_get_board_id(gpu_info, &board_id);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ SET_GPUINFO_STATIC(static_info, board_id, board_id);
+ }
+
+ if ((ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_mainboard_id)) ||
+ DCMI_SYMBOL_PRESENT(dcmi_get_mainboard_id)) {
+ unsigned mainboard_id = 0;
+ if (ascend_get_mainboard_id(gpu_info, &mainboard_id) == DCMI_SUCCESS)
+ SET_GPUINFO_STATIC(static_info, mainboard_id, mainboard_id);
+ }
+
+ if ((ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_pcie_slot_id)) ||
+ DCMI_SYMBOL_PRESENT(dcmi_get_card_pcie_slot)) {
+ int pcie_slot_id = -1;
+ if (ascend_get_pcie_slot_id(gpu_info, &pcie_slot_id) == DCMI_SUCCESS && pcie_slot_id >= 0) {
+ SET_GPUINFO_STATIC(static_info, pcie_slot_id, (unsigned)pcie_slot_id);
+ if (!GPUINFO_STATIC_FIELD_VALID(static_info, slot_id))
+ SET_GPUINFO_STATIC(static_info, slot_id, (unsigned)pcie_slot_id);
+ }
+ }
+
+ if (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_ub_slot_id)) {
+ int ub_slot_id = -1;
+ if (ascend_get_ub_slot_id(gpu_info, &ub_slot_id) == DCMI_SUCCESS && ub_slot_id >= 0)
+ SET_GPUINFO_STATIC(static_info, ub_slot_id, (unsigned)ub_slot_id);
+ }
+
+ if (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_ub_id_info)) {
+ struct dcmi_ub_id_info ub_id_info;
+ memset(&ub_id_info, 0, sizeof(ub_id_info));
+ if (ascend_get_ub_id_info(gpu_info, &ub_id_info) == DCMI_SUCCESS) {
+ SET_GPUINFO_STATIC(static_info, ub_device_id, ub_id_info.device_id);
+ SET_GPUINFO_STATIC(static_info, ub_vendor_id, ub_id_info.vendor_id);
+ SET_GPUINFO_STATIC(static_info, ub_module_vendor_id, ub_id_info.module_vendor_id);
+ SET_GPUINFO_STATIC(static_info, ub_module_id, ub_id_info.module_id);
+ }
+ }
+
+ unsigned chip_slot = 0;
+ unsigned chip_id = 0;
+ bool chip_id_valid = false;
+ if ((ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_slot_id_and_chip_id_by_dev_id)) ||
+ DCMI_SYMBOL_PRESENT(dcmi_get_device_chip_slot)) {
+ if (ascend_get_chip_location(gpu_info, &chip_slot, &chip_id, &chip_id_valid) == DCMI_SUCCESS) {
+ SET_GPUINFO_STATIC(static_info, chip_slot, chip_slot);
+ if (chip_id_valid)
+ SET_GPUINFO_STATIC(static_info, chip_id, chip_id);
+ }
+ }
+
+ if (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_group_intra_id_by_dev_id)) {
+ unsigned group_intra_id = 0;
+ if (ascend_get_group_intra_id(gpu_info, &group_intra_id) == DCMI_SUCCESS)
+ SET_GPUINFO_STATIC(static_info, group_intra_id, group_intra_id);
+ }
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_first_power_on_date)) {
+ unsigned first_power_on_date = 0;
+ /* DCMI uses zero when the MCU has not recorded a date yet. */
+ if (ascend_get_first_power_on_date(gpu_info, &first_power_on_date) == DCMI_SUCCESS && first_power_on_date != 0)
+ SET_GPUINFO_STATIC(static_info, first_power_on_date, first_power_on_date);
+ }
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_aicpu_count_info)) {
+ unsigned char aicpu_count = 0;
+ if (ascend_get_aicpu_count_config(gpu_info, &aicpu_count) == DCMI_SUCCESS)
+ SET_GPUINFO_STATIC(static_info, aicpu_count, (unsigned)aicpu_count);
+ }
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_cpu_num_config)) {
+ unsigned char cpu_config[ASCEND_CPU_NUM_CONFIG_SIZE] = {0};
+ if (ascend_get_cpu_num_config(gpu_info, cpu_config, sizeof(cpu_config)) == DCMI_SUCCESS) {
+ /* CANN's driver buffer is [Ctrl, Data, AI], despite npu-smi's public
+ * display order of AI, Ctrl, Data. */
+ SET_GPUINFO_STATIC(static_info, cpu_config_aicpu, (unsigned)cpu_config[2]);
+ SET_GPUINFO_STATIC(static_info, cpu_config_ctrlcpu, (unsigned)cpu_config[0]);
+ SET_GPUINFO_STATIC(static_info, cpu_config_datacpu, (unsigned)cpu_config[1]);
+ }
+ }
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_cpu_freq_info)) {
+ int cpu_freq_mode = -1;
+ if (ascend_get_cpu_freq_mode(gpu_info, &cpu_freq_mode) == DCMI_SUCCESS &&
+ (cpu_freq_mode == 0 || cpu_freq_mode == 1))
+ SET_GPUINFO_STATIC(static_info, cpu_freq_mode, (unsigned)cpu_freq_mode);
+ }
+
+ if (ascend_driver_version_valid) {
+ ascend_copy_name(static_info->driver_version, sizeof(static_info->driver_version),
+ (const unsigned char *)ascend_driver_version, sizeof(ascend_driver_version));
+ SET_VALID(gpuinfo_driver_version_valid, static_info->valid);
+ }
+ if (ascend_dcmi_version_valid) {
+ ascend_copy_name(static_info->dcmi_version, sizeof(static_info->dcmi_version),
+ (const unsigned char *)ascend_dcmi_version, sizeof(ascend_dcmi_version));
+ SET_VALID(gpuinfo_dcmi_version_valid, static_info->valid);
+ }
+
+ if ((ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_elabel_info)) ||
+ DCMI_SYMBOL_PRESENT(dcmi_get_device_elabel_info)) {
+ struct dcmi_elabel_info elabel_info;
+ memset(&elabel_info, 0, sizeof(elabel_info));
+ if (ascend_get_elabel_info(gpu_info, &elabel_info) == DCMI_SUCCESS) {
+ ascend_set_static_string(static_info->elabel_product_name, sizeof(static_info->elabel_product_name),
+ (const unsigned char *)elabel_info.product_name, sizeof(elabel_info.product_name),
+ gpuinfo_elabel_product_name_valid, static_info->valid);
+ ascend_set_static_string(static_info->elabel_model, sizeof(static_info->elabel_model),
+ (const unsigned char *)elabel_info.model, sizeof(elabel_info.model),
+ gpuinfo_elabel_model_valid, static_info->valid);
+ ascend_set_static_string(static_info->elabel_manufacturer, sizeof(static_info->elabel_manufacturer),
+ (const unsigned char *)elabel_info.manufacturer, sizeof(elabel_info.manufacturer),
+ gpuinfo_elabel_manufacturer_valid, static_info->valid);
+ ascend_set_static_string(static_info->elabel_manufacturer_date, sizeof(static_info->elabel_manufacturer_date),
+ (const unsigned char *)elabel_info.manufacturer_date,
+ sizeof(elabel_info.manufacturer_date), gpuinfo_elabel_manufacturer_date_valid,
+ static_info->valid);
+ ascend_set_static_string(static_info->elabel_serial_number, sizeof(static_info->elabel_serial_number),
+ (const unsigned char *)elabel_info.serial_number, sizeof(elabel_info.serial_number),
+ gpuinfo_elabel_serial_number_valid, static_info->valid);
+ }
+ }
+
+ /* Use the driver's component list when available. This avoids assuming a
+ * firmware component exists on a product where it is not exposed. */
+ if (DCMI_SYMBOL_PRESENT(dcmiv2_get_device_component_static_version) ||
+ DCMI_SYMBOL_PRESENT(dcmi_get_device_component_static_version)) {
+ enum dcmi_component_type firmware_components[32];
+ unsigned component_count = 0;
+ int component_status = ascend_get_component_count(gpu_info, &component_count);
+ if (component_status == DCMI_SUCCESS && component_count > 0 && component_count <= 32 &&
+ ascend_get_component_list(gpu_info, firmware_components, component_count) == DCMI_SUCCESS) {
+ for (unsigned i = 0; i < component_count; ++i) {
+ unsigned char firmware[MAX_VERSION_STRING];
+ memset(firmware, 0, sizeof(firmware));
+ if (ascend_get_component_version(gpu_info, firmware_components[i], firmware, sizeof(firmware)) ==
+ DCMI_SUCCESS &&
+ !ascend_name_is_empty(firmware, sizeof(firmware))) {
+ ascend_copy_name(static_info->firmware_version, sizeof(static_info->firmware_version), firmware,
+ sizeof(firmware));
+ SET_VALID(gpuinfo_firmware_version_valid, static_info->valid);
+ break;
+ }
+ }
+ } else {
+ /* Older libraries do not expose component enumeration. Keep a bounded
+ * compatibility probe for the component names used by those releases. */
+ static const enum dcmi_component_type fallback_components[] = {
+ DCMI_COMPONENT_TYPE_HILINK, DCMI_COMPONENT_TYPE_IMU, DCMI_COMPONENT_TYPE_XLOADER};
+ for (size_t i = 0; i < sizeof(fallback_components) / sizeof(fallback_components[0]); ++i) {
+ unsigned char firmware[MAX_VERSION_STRING];
+ memset(firmware, 0, sizeof(firmware));
+ if (ascend_get_component_version(gpu_info, fallback_components[i], firmware, sizeof(firmware)) ==
+ DCMI_SUCCESS &&
+ !ascend_name_is_empty(firmware, sizeof(firmware))) {
+ ascend_copy_name(static_info->firmware_version, sizeof(static_info->firmware_version), firmware,
+ sizeof(firmware));
+ SET_VALID(gpuinfo_firmware_version_valid, static_info->valid);
+ break;
+ }
+ }
+ }
+ }
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_sensor_info) ||
+ (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_sensor_info))) {
+ union dcmi_sensor_info threshold;
+ memset(&threshold, 0, sizeof(threshold));
+ if (ascend_get_sensor_info(gpu_info, DCMI_THERMAL_THRESHOLD_ID, &threshold) == DCMI_SUCCESS) {
+ if ((unsigned char)threshold.temp[0] > 0 && (unsigned char)threshold.temp[0] <= 200)
+ SET_GPUINFO_STATIC(static_info, temperature_slowdown_threshold, (unsigned char)threshold.temp[0]);
+ if ((unsigned char)threshold.temp[1] > 0 && (unsigned char)threshold.temp[1] <= 200)
+ SET_GPUINFO_STATIC(static_info, temperature_shutdown_threshold, (unsigned char)threshold.temp[1]);
+ }
+ }
+
+ if ((ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_hbm_product_info)) ||
+ DCMI_SYMBOL_PRESENT(dcmi_get_device_hbm_product_info)) {
+ struct dcmi_hbm_product_info hbm_product_info;
+ memset(&hbm_product_info, 0, sizeof(hbm_product_info));
+ last_dcmi_return_status = ascend_get_hbm_product_info(gpu_info, &hbm_product_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ SET_GPUINFO_STATIC(static_info, hbm_manufacturer_id, hbm_product_info.manufacturer_id);
+ }
+
+ ascend_populate_die_id(static_info, gpu_info);
+ ascend_populate_vrd_and_affinity(static_info, gpu_info);
+ ascend_populate_flash_inventory(static_info, gpu_info);
+ ascend_populate_netdevs(static_info, gpu_info);
+
+ ascend_set_memory_type(static_info, gpu_info);
+
+ unsigned max_link_width = 0;
+ unsigned max_link_speed = 0;
+ ascend_read_pcie_file(gpu_info->base.pdev, "max_link_width", &max_link_width);
+ ascend_read_pcie_file(gpu_info->base.pdev, "max_link_speed", &max_link_speed);
+ if (max_link_width > 0)
+ SET_GPUINFO_STATIC(static_info, max_pcie_link_width, max_link_width);
+ if (max_link_speed > 0) {
+ unsigned max_link_gen = nvtop_pcie_gen_from_link_speed(max_link_speed);
+ if (max_link_gen > 0)
+ SET_GPUINFO_STATIC(static_info, max_pcie_gen, max_link_gen);
+ }
+}
+
+static void gpuinfo_ascend_refresh_dynamic_info(struct gpu_info *_gpu_info) {
+ struct gpu_info_ascend *gpu_info = container_of(_gpu_info, struct gpu_info_ascend, base);
+ struct gpuinfo_dynamic_info *dynamic_info = &gpu_info->base.dynamic_info;
+ struct ascend_memory_sample memory_sample;
+ bool got_aicore_utilization = false;
+ bool got_vector_utilization = false;
+ bool got_aicube_utilization = false;
+ bool got_npu_utilization = false;
+ bool got_aicpu_utilization = false;
+
+ memset(dynamic_info, 0, sizeof(*dynamic_info));
+ pthread_mutex_lock(&ascend_cache_mutex);
+ ascend_apply_slow_status(gpu_info, dynamic_info);
+ ascend_apply_extended_status(gpu_info, dynamic_info);
+ pthread_mutex_unlock(&ascend_cache_mutex);
+
+ bool got_aicore_current = false;
+ bool got_aicore_max = false;
+ if ((ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_aicore_info)) ||
+ (ascend_has_legacy_ids(gpu_info) &&
+ (DCMI_SYMBOL_PRESENT(dcmi_get_device_aicore_info) || DCMI_SYMBOL_PRESENT(dcmi_get_aicore_info)))) {
+ struct dcmi_aicore_info aicore_info;
+ memset(&aicore_info, 0, sizeof(aicore_info));
+ last_dcmi_return_status = ascend_get_aicore_info(gpu_info, &aicore_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ if (aicore_info.cur_freq > 0)
+ SET_GPUINFO_DYNAMIC(dynamic_info, gpu_clock_speed, aicore_info.cur_freq);
+ if (aicore_info.freq > 0)
+ SET_GPUINFO_DYNAMIC(dynamic_info, gpu_clock_speed_max, aicore_info.freq);
+ got_aicore_current = aicore_info.cur_freq > 0;
+ got_aicore_max = aicore_info.freq > 0;
+ }
+ }
+ if (!got_aicore_current || !got_aicore_max) {
+ unsigned frequency = 0;
+ if (!got_aicore_current) {
+ last_dcmi_return_status = ascend_get_frequency(gpu_info, DCMI_FREQ_AICORE_CURRENT_, &frequency);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ SET_GPUINFO_DYNAMIC(dynamic_info, gpu_clock_speed, frequency);
+ }
+ if (!got_aicore_max) {
+ last_dcmi_return_status = ascend_get_frequency(gpu_info, DCMI_FREQ_AICORE_MAX, &frequency);
+ if (last_dcmi_return_status == DCMI_SUCCESS)
+ SET_GPUINFO_DYNAMIC(dynamic_info, gpu_clock_speed_max, frequency);
+ }
+ }
+
+ if (ascend_query_memory(gpu_info, &memory_sample)) {
+ /* DCMI memory sizes are documented in MB. */
+ unsigned long long multiplier = 1024ULL * 1024ULL;
+ unsigned long long total_bytes = ascend_to_bytes(memory_sample.total, multiplier);
+ SET_GPUINFO_DYNAMIC(dynamic_info, total_memory, total_bytes);
+ if (memory_sample.has_used) {
+ unsigned long long used_bytes = ascend_to_bytes(memory_sample.used, multiplier);
+ if (used_bytes > total_bytes)
+ used_bytes = total_bytes;
+ SET_GPUINFO_DYNAMIC(dynamic_info, used_memory, used_bytes);
+ if (memory_sample.has_available) {
+ unsigned long long free_bytes = ascend_to_bytes(memory_sample.available, multiplier);
+ if (free_bytes > total_bytes)
+ free_bytes = total_bytes;
+ SET_GPUINFO_DYNAMIC(dynamic_info, free_memory, free_bytes);
+ } else {
+ SET_GPUINFO_DYNAMIC(dynamic_info, free_memory, total_bytes - used_bytes);
+ }
+ }
+ if (memory_sample.utilization_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, mem_util_rate, memory_sample.utilization);
+ if (memory_sample.frequency > 0)
+ SET_GPUINFO_DYNAMIC(dynamic_info, mem_clock_speed, memory_sample.frequency);
+ unsigned memory_max_frequency = 0;
+ enum dcmi_freq_type memory_frequency_type =
+ memory_sample.source == ASCEND_MEMORY_HBM ? DCMI_FREQ_HBM : DCMI_FREQ_DDR;
+ if (ascend_get_frequency(gpu_info, memory_frequency_type, &memory_max_frequency) == DCMI_SUCCESS &&
+ memory_max_frequency > 0)
+ SET_GPUINFO_DYNAMIC(dynamic_info, mem_clock_speed_max, memory_max_frequency);
+ if (memory_sample.source == ASCEND_MEMORY_HBM) {
+ if (memory_sample.bandwidth_utilization_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, mem_bandwidth_util_rate, memory_sample.bandwidth_utilization);
+ if (memory_sample.temperature_valid)
+ SET_GPUINFO_DYNAMIC(dynamic_info, mem_temp, (unsigned)memory_sample.temperature);
+ }
+
+ unsigned bandwidth_utilization = 0;
+ int bandwidth_type = memory_sample.source == ASCEND_MEMORY_HBM ? DCMI_UTILIZATION_RATE_HBM_BANDWIDTH
+ : DCMI_UTILIZATION_RATE_DDR_BANDWIDTH;
+ if (ascend_query_utilization(gpu_info, bandwidth_type, &bandwidth_utilization))
+ SET_GPUINFO_DYNAMIC(dynamic_info, mem_bandwidth_util_rate, bandwidth_utilization);
+ }
+
+ unsigned utilization = 0;
+ if (ascend_query_utilization(gpu_info, DCMI_UTILIZATION_RATE_AICORE, &utilization)) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, gpu_util_rate, utilization);
+ got_aicore_utilization = true;
+ }
+ if (ascend_query_utilization(gpu_info, DCMI_UTILIZATION_RATE_VECTORCORE, &utilization)) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, vector_util_rate, utilization);
+ got_vector_utilization = true;
+ }
+ if (ascend_query_utilization(gpu_info, DCMI_UTILIZATION_RATE_AICUBE, &utilization)) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, aicube_util_rate, utilization);
+ got_aicube_utilization = true;
+ }
+ if (ascend_query_utilization(gpu_info, DCMI_UTILIZATION_RATE_NPU, &utilization)) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, npu_util_rate, utilization);
+ got_npu_utilization = true;
+ }
+
+ if ((ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_multi_utilization_rate)) ||
+ DCMI_SYMBOL_PRESENT(dcmi_get_device_multi_utilization_rate)) {
+ struct dcmi_multi_utilization_info multi_utilization;
+ memset(&multi_utilization, 0, sizeof(multi_utilization));
+ last_dcmi_return_status = ascend_get_multi_utilization(gpu_info, &multi_utilization);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ if (!got_aicore_utilization) {
+ if (ascend_percentage_is_valid(multi_utilization.aicore_util)) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, gpu_util_rate, multi_utilization.aicore_util);
+ got_aicore_utilization = true;
+ }
+ }
+ if (!got_vector_utilization && ascend_percentage_is_valid(multi_utilization.aiv_util))
+ SET_GPUINFO_DYNAMIC(dynamic_info, vector_util_rate, multi_utilization.aiv_util);
+ if (!got_aicube_utilization && ascend_percentage_is_valid(multi_utilization.aic_util))
+ SET_GPUINFO_DYNAMIC(dynamic_info, aicube_util_rate, multi_utilization.aic_util);
+ if (!got_npu_utilization && ascend_percentage_is_valid(multi_utilization.npu_util))
+ SET_GPUINFO_DYNAMIC(dynamic_info, npu_util_rate, multi_utilization.npu_util);
+ }
+ }
+
+ if ((ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_aicpu_info)) ||
+ (ascend_has_legacy_ids(gpu_info) &&
+ (DCMI_SYMBOL_PRESENT(dcmi_get_device_aicpu_info) || DCMI_SYMBOL_PRESENT(dcmi_get_aicpu_info)))) {
+ struct dcmi_aicpu_info aicpu_info;
+ memset(&aicpu_info, 0, sizeof(aicpu_info));
+ last_dcmi_return_status = ascend_get_aicpu_info(gpu_info, &aicpu_info);
+ if (last_dcmi_return_status == DCMI_SUCCESS) {
+ if (aicpu_info.cur_freq > 0)
+ SET_GPUINFO_DYNAMIC(dynamic_info, aicpu_clock_speed, aicpu_info.cur_freq);
+ if (aicpu_info.max_freq > 0)
+ SET_GPUINFO_DYNAMIC(dynamic_info, aicpu_clock_speed_max, aicpu_info.max_freq);
+ unsigned count = aicpu_info.aicpu_num > MAX_CORE_NUM ? MAX_CORE_NUM : aicpu_info.aicpu_num;
+ if (count > 0) {
+ unsigned long long total = 0;
+ for (unsigned i = 0; i < count; ++i)
+ total += aicpu_info.util_rate[i] > 100 ? 100 : aicpu_info.util_rate[i];
+ SET_GPUINFO_DYNAMIC(dynamic_info, aicpu_util_rate, (unsigned)(total / count));
+ got_aicpu_utilization = true;
+ }
+ }
+ }
+ if (!got_aicpu_utilization && ascend_query_utilization(gpu_info, DCMI_UTILIZATION_RATE_AICPU, &utilization))
+ SET_GPUINFO_DYNAMIC(dynamic_info, aicpu_util_rate, utilization);
+ if (ascend_query_utilization(gpu_info, DCMI_UTILIZATION_RATE_CTRLCPU, &utilization)) {
+ SET_GPUINFO_DYNAMIC(dynamic_info, ctrlcpu_util_rate, utilization);
+ }
+
+ int temperature = 0;
+ last_dcmi_return_status = ascend_get_temperature(gpu_info, &temperature);
+ if (last_dcmi_return_status == DCMI_SUCCESS && temperature >= 0)
+ SET_GPUINFO_DYNAMIC(dynamic_info, gpu_temp, (unsigned)temperature);
+
+ int power = 0;
+ last_dcmi_return_status = ascend_get_power(gpu_info, &power);
+ if (last_dcmi_return_status == DCMI_SUCCESS && power >= 0 && (unsigned)power <= UINT_MAX / 100)
+ /* DCMI reports tenths of a watt; nvtop stores milliwatts. */
+ SET_GPUINFO_DYNAMIC(dynamic_info, power_draw, (unsigned)power * 100);
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_voltage) ||
+ (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_voltage))) {
+ unsigned voltage = 0;
+ last_dcmi_return_status = ascend_get_voltage(gpu_info, &voltage);
+ if (last_dcmi_return_status == DCMI_SUCCESS && ascend_voltage_is_valid(voltage) && voltage <= UINT_MAX / 10)
+ /* DCMI voltage has a 0.01 V resolution; nvtop stores millivolts. */
+ SET_GPUINFO_DYNAMIC(dynamic_info, voltage, voltage * 10);
+ }
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_health) ||
+ (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_health))) {
+ unsigned health = 0;
+ last_dcmi_return_status = ascend_get_health(gpu_info, &health);
+ if (last_dcmi_return_status == DCMI_SUCCESS && health <= 3)
+ SET_GPUINFO_DYNAMIC(dynamic_info, health, health);
+ }
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_driver_health) ||
+ (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_driver_health))) {
+ unsigned driver_health = 0;
+ last_dcmi_return_status = ascend_get_driver_health(&driver_health);
+ if (last_dcmi_return_status == DCMI_SUCCESS && driver_health <= 3)
+ SET_GPUINFO_DYNAMIC(dynamic_info, driver_health, driver_health);
+ }
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_device_errorcode_v2) ||
+ (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_device_error_code_list))) {
+ int error_count = 0;
+ unsigned error_codes[GPUINFO_MAX_ERROR_CODES] = {0};
+ last_dcmi_return_status = ascend_get_error_codes(gpu_info, &error_count, error_codes, GPUINFO_MAX_ERROR_CODES);
+ if (last_dcmi_return_status == DCMI_SUCCESS && error_count >= 0) {
+ unsigned count =
+ (unsigned)error_count > GPUINFO_MAX_ERROR_CODES ? GPUINFO_MAX_ERROR_CODES : (unsigned)error_count;
+ dynamic_info->error_code_count = count;
+ memcpy(dynamic_info->error_codes, error_codes, count * sizeof(error_codes[0]));
+ SET_VALID(gpuinfo_error_codes_valid, dynamic_info->valid);
+ }
+ }
+
+ if (DCMI_SYMBOL_PRESENT(dcmi_get_driver_errorcode) ||
+ (ascend_use_dcmiv2 && DCMI_SYMBOL_PRESENT(dcmiv2_get_driver_error_code_list))) {
+ int error_count = 0;
+ unsigned error_codes[GPUINFO_MAX_ERROR_CODES] = {0};
+ last_dcmi_return_status = ascend_get_driver_error_codes(&error_count, error_codes, GPUINFO_MAX_ERROR_CODES);
+ if (last_dcmi_return_status == DCMI_SUCCESS && error_count >= 0) {
+ unsigned count =
+ (unsigned)error_count > GPUINFO_MAX_ERROR_CODES ? GPUINFO_MAX_ERROR_CODES : (unsigned)error_count;
+ dynamic_info->driver_error_code_count = count;
+ memcpy(dynamic_info->driver_error_codes, error_codes, count * sizeof(error_codes[0]));
+ SET_VALID(gpuinfo_driver_error_codes_valid, dynamic_info->valid);
+ }
+ }
+
+ ascend_refresh_ecc(gpu_info, dynamic_info);
+ ascend_refresh_pcie_errors(gpu_info, dynamic_info);
+ ascend_refresh_dvpp(gpu_info, dynamic_info);
+ ascend_refresh_fan(gpu_info, dynamic_info);
+ ascend_refresh_pcie_link(&gpu_info->base, dynamic_info);
+ pthread_mutex_lock(&ascend_cache_mutex);
+ ascend_apply_pcie_bandwidth(gpu_info, dynamic_info);
+ pthread_mutex_unlock(&ascend_cache_mutex);
+}
+
+static void gpuinfo_ascend_get_running_processes(struct gpu_info *_gpu_info) {
+ struct gpu_info_ascend *gpu_info = container_of(_gpu_info, struct gpu_info_ascend, base);
+ struct dcmi_proc_mem_info proc_info[MAX_PROC_NUM] = {0};
+ int proc_num = 0;
+
+ /* A failed management query must not leave the previous cycle's process
+ * list looking current. Keep the allocation for reuse, but publish an
+ * empty snapshot until DCMI returns a fresh result. */
+ _gpu_info->processes_count = 0;
+ last_dcmi_return_status = ascend_get_proc_mem_info(gpu_info, proc_info, &proc_num);
+ if (last_dcmi_return_status != DCMI_SUCCESS || proc_num < 0 || proc_num > MAX_PROC_NUM)
+ return;
+
+ unsigned new_array_size = (unsigned)proc_num + PROC_ALLOC_INC;
+ struct gpu_process *new_processes = reallocarray(_gpu_info->processes, new_array_size, sizeof(*new_processes));
+ if (!new_processes)
+ return;
+ _gpu_info->processes = new_processes;
+ _gpu_info->processes_array_size = new_array_size;
+ memset(_gpu_info->processes, 0, new_array_size * sizeof(*_gpu_info->processes));
+ _gpu_info->processes_count = (unsigned)proc_num;
+
+ for (int i = 0; i < proc_num; ++i) {
+ _gpu_info->processes[i].type = gpu_process_compute;
+ _gpu_info->processes[i].pid = proc_info[i].proc_id;
+ _gpu_info->processes[i].gpu_memory_usage = proc_info[i].proc_mem_usage;
+ SET_VALID(gpuinfo_process_gpu_memory_usage_valid, _gpu_info->processes[i].valid);
+ }
+}
diff --git a/src/interface.c b/src/interface.c
index ae231991..c30f1166 100644
--- a/src/interface.c
+++ b/src/interface.c
@@ -55,6 +55,46 @@ static unsigned int sizeof_process_field[process_field_count] = {
[process_cpu_usage] = 6, [process_cpu_mem_usage] = 9, [process_command] = 0,
};
+static void print_json_string(const char *value) {
+ if (value == NULL) {
+ fputs("null", stdout);
+ return;
+ }
+ putchar('"');
+ for (const unsigned char *cursor = (const unsigned char *)value; *cursor != '\0'; ++cursor) {
+ switch (*cursor) {
+ case '"':
+ fputs("\\\"", stdout);
+ break;
+ case '\\':
+ fputs("\\\\", stdout);
+ break;
+ case '\b':
+ fputs("\\b", stdout);
+ break;
+ case '\f':
+ fputs("\\f", stdout);
+ break;
+ case '\n':
+ fputs("\\n", stdout);
+ break;
+ case '\r':
+ fputs("\\r", stdout);
+ break;
+ case '\t':
+ fputs("\\t", stdout);
+ break;
+ default:
+ if (*cursor < 0x20)
+ printf("\\u%04x", (unsigned)*cursor);
+ else
+ putchar(*cursor);
+ break;
+ }
+ }
+ putchar('"');
+}
+
static void alloc_device_window(unsigned int start_row, unsigned int start_col, unsigned int totalcol,
struct device_window *dwin) {
@@ -806,10 +846,12 @@ static void draw_devices(struct list_head *devices, struct nvtop_interface *inte
// MEM CLOCK
werase(dev->mem_clock_info);
+ const char *mem_label =
+ GPUINFO_STATIC_FIELD_VALID(&device->static_info, memory_type) ? device->static_info.memory_type : "MEM";
if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, mem_clock_speed))
- mvwprintw(dev->mem_clock_info, 0, 0, "MEM %uMHz", device->dynamic_info.mem_clock_speed);
+ mvwprintw(dev->mem_clock_info, 0, 0, "%s %uMHz", mem_label, device->dynamic_info.mem_clock_speed);
else
- mvwprintw(dev->mem_clock_info, 0, 0, "MEM N/A MHz");
+ mvwprintw(dev->mem_clock_info, 0, 0, "%s N/A MHz", mem_label);
mvwchgat(dev->mem_clock_info, 0, 0, 3, 0, cyan_color, NULL);
wnoutrefresh(dev->mem_clock_info);
@@ -2164,25 +2206,209 @@ void print_snapshot(struct list_head *devices, bool use_fahrenheit_option, bool
const char *mem_used_field = "mem_used";
const char *mem_free_field = "mem_free";
+#define SNAPSHOT_STATIC_STRING(json_name, field_name) \
+ do { \
+ printf("%s\"%s\": ", indent_level_four, json_name); \
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, field_name)) \
+ print_json_string(device->static_info.field_name); \
+ else \
+ fputs("null", stdout); \
+ fputs(",\n", stdout); \
+ } while (0)
+
printf("%s{\n", indent_level_two);
// Device Name
- if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, device_name))
- printf("%s\"%s\": \"%s\",\n", indent_level_four, device_name_field, device->static_info.device_name);
+ SNAPSHOT_STATIC_STRING(device_name_field, device_name);
+
+ // Stable device identifier (PCI BDF when DCMI exposes it, otherwise the
+ // physical card/device tuple or logical-device fallback).
+ printf("%s\"pdev\": ", indent_level_four);
+ if (device->pdev[0] != '\0')
+ print_json_string(device->pdev);
+ else
+ fputs("null", stdout);
+ fputs(",\n", stdout);
+
+ // Memory Type
+ SNAPSHOT_STATIC_STRING("memory_type", memory_type);
+
+ // Chip and board metadata
+ SNAPSHOT_STATIC_STRING("chip_type", chip_type);
+ SNAPSHOT_STATIC_STRING("chip_version", chip_version);
+ SNAPSHOT_STATIC_STRING("npu_name", npu_name);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, board_id))
+ printf("%s\"board_id\": %u,\n", indent_level_four, device->static_info.board_id);
+ else
+ printf("%s\"board_id\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, pcb_id))
+ printf("%s\"pcb_id\": %u,\n", indent_level_four, device->static_info.pcb_id);
+ else
+ printf("%s\"pcb_id\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, bom_id))
+ printf("%s\"bom_id\": %u,\n", indent_level_four, device->static_info.bom_id);
+ else
+ printf("%s\"bom_id\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, slot_id))
+ printf("%s\"slot_id\": %u,\n", indent_level_four, device->static_info.slot_id);
+ else
+ printf("%s\"slot_id\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, mainboard_id))
+ printf("%s\"mainboard_id\": %u,\n", indent_level_four, device->static_info.mainboard_id);
+ else
+ printf("%s\"mainboard_id\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, pcie_slot_id))
+ printf("%s\"pcie_slot_id\": %u,\n", indent_level_four, device->static_info.pcie_slot_id);
+ else
+ printf("%s\"pcie_slot_id\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, ub_slot_id))
+ printf("%s\"ub_slot_id\": %u,\n", indent_level_four, device->static_info.ub_slot_id);
+ else
+ printf("%s\"ub_slot_id\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, ub_device_id))
+ printf("%s\"ub_device_id\": %u,\n", indent_level_four, device->static_info.ub_device_id);
+ else
+ printf("%s\"ub_device_id\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, ub_vendor_id))
+ printf("%s\"ub_vendor_id\": %u,\n", indent_level_four, device->static_info.ub_vendor_id);
else
- printf("%s\"%s\": null,\n", indent_level_four, device_name_field);
+ printf("%s\"ub_vendor_id\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, ub_module_vendor_id))
+ printf("%s\"ub_module_vendor_id\": %u,\n", indent_level_four, device->static_info.ub_module_vendor_id);
+ else
+ printf("%s\"ub_module_vendor_id\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, ub_module_id))
+ printf("%s\"ub_module_id\": %u,\n", indent_level_four, device->static_info.ub_module_id);
+ else
+ printf("%s\"ub_module_id\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, chip_id))
+ printf("%s\"chip_id\": %u,\n", indent_level_four, device->static_info.chip_id);
+ else
+ printf("%s\"chip_id\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, chip_slot))
+ printf("%s\"chip_slot\": %u,\n", indent_level_four, device->static_info.chip_slot);
+ else
+ printf("%s\"chip_slot\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, group_intra_id))
+ printf("%s\"group_intra_id\": %u,\n", indent_level_four, device->static_info.group_intra_id);
+ else
+ printf("%s\"group_intra_id\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, first_power_on_date))
+ printf("%s\"first_power_on_date\": %u,\n", indent_level_four, device->static_info.first_power_on_date);
+ else
+ printf("%s\"first_power_on_date\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, aicpu_count))
+ printf("%s\"aicpu_count\": %u,\n", indent_level_four, device->static_info.aicpu_count);
+ else
+ printf("%s\"aicpu_count\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, cpu_config_aicpu))
+ printf("%s\"cpu_config_aicpu\": %u,\n", indent_level_four, device->static_info.cpu_config_aicpu);
+ else
+ printf("%s\"cpu_config_aicpu\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, cpu_config_ctrlcpu))
+ printf("%s\"cpu_config_ctrlcpu\": %u,\n", indent_level_four, device->static_info.cpu_config_ctrlcpu);
+ else
+ printf("%s\"cpu_config_ctrlcpu\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, cpu_config_datacpu))
+ printf("%s\"cpu_config_datacpu\": %u,\n", indent_level_four, device->static_info.cpu_config_datacpu);
+ else
+ printf("%s\"cpu_config_datacpu\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, cpu_freq_mode))
+ printf("%s\"cpu_freq_mode\": %u,\n", indent_level_four, device->static_info.cpu_freq_mode);
+ else
+ printf("%s\"cpu_freq_mode\": null,\n", indent_level_four);
+ SNAPSHOT_STATIC_STRING("driver_version", driver_version);
+ SNAPSHOT_STATIC_STRING("dcmi_version", dcmi_version);
+ SNAPSHOT_STATIC_STRING("firmware_version", firmware_version);
+ SNAPSHOT_STATIC_STRING("elabel_product_name", elabel_product_name);
+ SNAPSHOT_STATIC_STRING("elabel_model", elabel_model);
+ SNAPSHOT_STATIC_STRING("elabel_manufacturer", elabel_manufacturer);
+ SNAPSHOT_STATIC_STRING("elabel_manufacturer_date", elabel_manufacturer_date);
+ SNAPSHOT_STATIC_STRING("elabel_serial_number", elabel_serial_number);
+ SNAPSHOT_STATIC_STRING("die_id", die_id);
+ SNAPSHOT_STATIC_STRING("vrd_version", vrd_version);
+ SNAPSHOT_STATIC_STRING("affinity_cpu", affinity_cpu);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, flash_inventory)) {
+ unsigned flash_inventory_count = device->static_info.flash_inventory_count > GPUINFO_MAX_FLASHES
+ ? GPUINFO_MAX_FLASHES
+ : device->static_info.flash_inventory_count;
+ printf("%s\"flash_count\": %u,\n", indent_level_four, device->static_info.flash_count);
+ printf("%s\"flash_inventory\": [", indent_level_four);
+ for (unsigned i = 0; i < flash_inventory_count; ++i) {
+ const struct gpuinfo_flash_info *flash = &device->static_info.flashes[i];
+ if (i > 0)
+ fputs(", ", stdout);
+ printf("{\"flash_id\": %llu, \"device_id\": %u, \"vendor\": %u, \"state\": %u, "
+ "\"size\": %llu, \"sector_count\": %u, \"manufacturer_id\": %u}",
+ flash->flash_id, flash->device_id, flash->vendor, flash->state, flash->size, flash->sector_count,
+ flash->manufacturer_id);
+ }
+ fputs("],\n", stdout);
+ } else {
+ printf("%s\"flash_count\": null,\n", indent_level_four);
+ printf("%s\"flash_inventory\": null,\n", indent_level_four);
+ }
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, netdev_names)) {
+ unsigned count = device->static_info.netdev_count > GPUINFO_MAX_NETDEVS ? GPUINFO_MAX_NETDEVS
+ : device->static_info.netdev_count;
+ printf("%s\"netdev_count\": %u,\n", indent_level_four, device->static_info.netdev_count);
+ printf("%s\"netdev_names\": [", indent_level_four);
+ for (unsigned i = 0; i < count; ++i) {
+ if (i > 0)
+ fputs(", ", stdout);
+ print_json_string(device->static_info.netdev_names[i]);
+ }
+ fputs("],\n", stdout);
+ } else {
+ printf("%s\"netdev_count\": null,\n", indent_level_four);
+ printf("%s\"netdev_names\": null,\n", indent_level_four);
+ }
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, hbm_manufacturer_id))
+ printf("%s\"hbm_manufacturer_id\": %u,\n", indent_level_four, device->static_info.hbm_manufacturer_id);
+ else
+ printf("%s\"hbm_manufacturer_id\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, max_pcie_gen))
+ printf("%s\"max_pcie_gen\": %u,\n", indent_level_four, device->static_info.max_pcie_gen);
+ else
+ printf("%s\"max_pcie_gen\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, max_pcie_link_width))
+ printf("%s\"max_pcie_width\": %u,\n", indent_level_four, device->static_info.max_pcie_link_width);
+ else
+ printf("%s\"max_pcie_width\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, n_shared_cores))
+ printf("%s\"shared_cores\": %u,\n", indent_level_four, device->static_info.n_shared_cores);
+ else
+ printf("%s\"shared_cores\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, temperature_slowdown_threshold))
+ printf("%s\"temperature_slowdown_threshold\": \"%uC\",\n", indent_level_four,
+ device->static_info.temperature_slowdown_threshold);
+ else
+ printf("%s\"temperature_slowdown_threshold\": null,\n", indent_level_four);
+ if (GPUINFO_STATIC_FIELD_VALID(&device->static_info, temperature_shutdown_threshold))
+ printf("%s\"temperature_shutdown_threshold\": \"%uC\",\n", indent_level_four,
+ device->static_info.temperature_shutdown_threshold);
+ else
+ printf("%s\"temperature_shutdown_threshold\": null,\n", indent_level_four);
// GPU Clock Speed
if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, gpu_clock_speed))
printf("%s\"%s\": \"%uMHz\",\n", indent_level_four, gpu_clock_field, device->dynamic_info.gpu_clock_speed);
else
printf("%s\"%s\": null,\n", indent_level_four, gpu_clock_field);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, gpu_clock_speed_max))
+ printf("%s\"gpu_clock_max\": \"%uMHz\",\n", indent_level_four, device->dynamic_info.gpu_clock_speed_max);
+ else
+ printf("%s\"gpu_clock_max\": null,\n", indent_level_four);
// MEM Clock Speed
if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, mem_clock_speed))
printf("%s\"%s\": \"%uMHz\",\n", indent_level_four, mem_clock_field, device->dynamic_info.mem_clock_speed);
else
printf("%s\"%s\": null,\n", indent_level_four, mem_clock_field);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, mem_clock_speed_max))
+ printf("%s\"mem_clock_max\": \"%uMHz\",\n", indent_level_four, device->dynamic_info.mem_clock_speed_max);
+ else
+ printf("%s\"mem_clock_max\": null,\n", indent_level_four);
// GPU Temperature
if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, gpu_temp)) {
@@ -2214,6 +2440,10 @@ void print_snapshot(struct list_head *devices, bool use_fahrenheit_option, bool
printf("%s\"%s\": \"%uW\",\n", indent_level_four, power_field, device->dynamic_info.power_draw / 1000);
else
printf("%s\"%s\": null,\n", indent_level_four, power_field);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, power_draw_max))
+ printf("%s\"power_draw_max\": \"%uW\",\n", indent_level_four, device->dynamic_info.power_draw_max / 1000);
+ else
+ printf("%s\"power_draw_max\": null,\n", indent_level_four);
// GPU Utilization
if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, gpu_util_rate))
@@ -2258,9 +2488,348 @@ void print_snapshot(struct list_head *devices, bool use_fahrenheit_option, bool
printf("%s\"%s\": null,\n", indent_level_four, mem_used_field);
// Memory Available
if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, free_memory))
- printf("%s\"%s\": \"%llu\"", indent_level_four, mem_free_field, device->dynamic_info.free_memory);
+ printf("%s\"%s\": \"%llu\",\n", indent_level_four, mem_free_field, device->dynamic_info.free_memory);
+ else
+ printf("%s\"%s\": null,\n", indent_level_four, mem_free_field);
+
+#define SNAPSHOT_PERCENT(json_name, field_name) \
+ do { \
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, field_name)) \
+ printf("%s\"%s\": \"%u%%\",\n", indent_level_four, json_name, device->dynamic_info.field_name); \
+ else \
+ printf("%s\"%s\": null,\n", indent_level_four, json_name); \
+ } while (0)
+#define SNAPSHOT_MHZ(json_name, field_name) \
+ do { \
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, field_name)) \
+ printf("%s\"%s\": \"%uMHz\",\n", indent_level_four, json_name, device->dynamic_info.field_name); \
+ else \
+ printf("%s\"%s\": null,\n", indent_level_four, json_name); \
+ } while (0)
+#define SNAPSHOT_TEMP(json_name, field_name) \
+ do { \
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, field_name)) \
+ printf("%s\"%s\": \"%uC\",\n", indent_level_four, json_name, device->dynamic_info.field_name); \
+ else \
+ printf("%s\"%s\": null,\n", indent_level_four, json_name); \
+ } while (0)
+#define SNAPSHOT_COUNT(json_name, field_name) \
+ do { \
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, field_name)) \
+ printf("%s\"%s\": %u,\n", indent_level_four, json_name, device->dynamic_info.field_name); \
+ else \
+ printf("%s\"%s\": null,\n", indent_level_four, json_name); \
+ } while (0)
+
+ // Additional Ascend telemetry
+ SNAPSHOT_MHZ("aicpu_clock", aicpu_clock_speed);
+ SNAPSHOT_MHZ("aicpu_clock_max", aicpu_clock_speed_max);
+ SNAPSHOT_PERCENT("aicpu_util", aicpu_util_rate);
+ SNAPSHOT_PERCENT("ctrlcpu_util", ctrlcpu_util_rate);
+ SNAPSHOT_PERCENT("vector_util", vector_util_rate);
+ SNAPSHOT_PERCENT("aicube_util", aicube_util_rate);
+ SNAPSHOT_PERCENT("npu_util", npu_util_rate);
+ SNAPSHOT_PERCENT("mem_bandwidth_util", mem_bandwidth_util_rate);
+ SNAPSHOT_TEMP("mem_temp", mem_temp);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, pcie_link_gen))
+ printf("%s\"pcie_link_gen\": %u,\n", indent_level_four, device->dynamic_info.pcie_link_gen);
+ else
+ printf("%s\"pcie_link_gen\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, pcie_link_width))
+ printf("%s\"pcie_link_width\": %u,\n", indent_level_four, device->dynamic_info.pcie_link_width);
else
- printf("%s\"%s\": null", indent_level_four, mem_free_field);
+ printf("%s\"pcie_link_width\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, pcie_rx))
+ printf("%s\"pcie_rx\": \"%uKB/s\",\n", indent_level_four, device->dynamic_info.pcie_rx);
+ else
+ printf("%s\"pcie_rx\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, pcie_tx))
+ printf("%s\"pcie_tx\": \"%uKB/s\",\n", indent_level_four, device->dynamic_info.pcie_tx);
+ else
+ printf("%s\"pcie_tx\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, voltage))
+ printf("%s\"voltage\": \"%umV\",\n", indent_level_four, device->dynamic_info.voltage);
+ else
+ printf("%s\"voltage\": null,\n", indent_level_four);
+
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, health)) {
+ static const char *const health_names[] = {"OK", "WARNING", "MAJOR", "CRITICAL"};
+ unsigned health = device->dynamic_info.health;
+ printf("%s\"health\": \"%s\",\n", indent_level_four,
+ health < sizeof(health_names) / sizeof(health_names[0]) ? health_names[health] : "UNKNOWN");
+ printf("%s\"health_code\": %u,\n", indent_level_four, health);
+ } else {
+ printf("%s\"health\": null,\n", indent_level_four);
+ printf("%s\"health_code\": null,\n", indent_level_four);
+ }
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, driver_health)) {
+ static const char *const driver_health_names[] = {"OK", "WARNING", "MAJOR", "CRITICAL"};
+ unsigned driver_health = device->dynamic_info.driver_health;
+ printf("%s\"driver_health\": \"%s\",\n", indent_level_four,
+ driver_health < sizeof(driver_health_names) / sizeof(driver_health_names[0])
+ ? driver_health_names[driver_health]
+ : "UNKNOWN");
+ printf("%s\"driver_health_code\": %u,\n", indent_level_four, driver_health);
+ } else {
+ printf("%s\"driver_health\": null,\n", indent_level_four);
+ printf("%s\"driver_health_code\": null,\n", indent_level_four);
+ }
+
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, boot_status)) {
+ static const char *const boot_status_names[] = {"UNINIT", "BIOS", "OS", "FINISH"};
+ unsigned boot_status = device->dynamic_info.boot_status;
+ const char *name = boot_status == 16u ? "SYSTEM_START_FINISH"
+ : (boot_status < sizeof(boot_status_names) / sizeof(boot_status_names[0])
+ ? boot_status_names[boot_status]
+ : "UNKNOWN");
+ printf("%s\"boot_status\": \"%s\",\n", indent_level_four, name);
+ printf("%s\"boot_status_code\": %u,\n", indent_level_four, boot_status);
+ } else {
+ printf("%s\"boot_status\": null,\n", indent_level_four);
+ printf("%s\"boot_status_code\": null,\n", indent_level_four);
+ }
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, compatibility)) {
+ static const char *const compatibility_names[] = {"UNKNOWN", "OK", "NOK", "UNKNOWN"};
+ unsigned compatibility = device->dynamic_info.compatibility;
+ const char *name = compatibility < sizeof(compatibility_names) / sizeof(compatibility_names[0])
+ ? compatibility_names[compatibility]
+ : "UNKNOWN";
+ printf("%s\"compatibility\": \"%s\",\n", indent_level_four, name);
+ printf("%s\"compatibility_code\": %u,\n", indent_level_four, compatibility);
+ } else {
+ printf("%s\"compatibility\": null,\n", indent_level_four);
+ printf("%s\"compatibility_code\": null,\n", indent_level_four);
+ }
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, network_health)) {
+ static const char *const network_health_names[] = {
+ "OK", "SOCKET_FAIL", "RECV_TIMEOUT", "UNREACH", "TIME_EXCEEDED", "FAULT", "INIT", "THREAD_ERR", "IP_SET"};
+ unsigned network_health = device->dynamic_info.network_health;
+ const char *name = network_health < sizeof(network_health_names) / sizeof(network_health_names[0])
+ ? network_health_names[network_health]
+ : "UNKNOWN";
+ printf("%s\"network_health\": \"%s\",\n", indent_level_four, name);
+ printf("%s\"network_health_code\": %u,\n", indent_level_four, network_health);
+ } else {
+ printf("%s\"network_health\": null,\n", indent_level_four);
+ printf("%s\"network_health_code\": null,\n", indent_level_four);
+ }
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, outband_channel_state)) {
+ unsigned outband_state = device->dynamic_info.outband_channel_state;
+ printf("%s\"outband_channel_state\": %u,\n", indent_level_four, outband_state);
+ } else {
+ printf("%s\"outband_channel_state\": null,\n", indent_level_four);
+ }
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, device_share_enabled))
+ printf("%s\"device_share_enabled\": %s,\n", indent_level_four,
+ device->dynamic_info.device_share_enabled ? "true" : "false");
+ else
+ printf("%s\"device_share_enabled\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, p2p_enabled))
+ printf("%s\"p2p_enabled\": %s,\n", indent_level_four, device->dynamic_info.p2p_enabled ? "true" : "false");
+ else
+ printf("%s\"p2p_enabled\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, cgroup_memory_limit))
+ printf("%s\"cgroup_memory_limit\": %llu,\n", indent_level_four, device->dynamic_info.cgroup_memory_limit);
+ else
+ printf("%s\"cgroup_memory_limit\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, cgroup_memory_usage))
+ printf("%s\"cgroup_memory_usage\": %llu,\n", indent_level_four, device->dynamic_info.cgroup_memory_usage);
+ else
+ printf("%s\"cgroup_memory_usage\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, cgroup_memory_max_usage))
+ printf("%s\"cgroup_memory_max_usage\": %llu,\n", indent_level_four, device->dynamic_info.cgroup_memory_max_usage);
+ else
+ printf("%s\"cgroup_memory_max_usage\": null,\n", indent_level_four);
+ SNAPSHOT_PERCENT("llc_read_hit_rate", llc_read_hit_rate);
+ SNAPSHOT_PERCENT("llc_write_hit_rate", llc_write_hit_rate);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, llc_throughput))
+ printf("%s\"llc_throughput\": %u,\n", indent_level_four, device->dynamic_info.llc_throughput);
+ else
+ printf("%s\"llc_throughput\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, error_codes)) {
+ printf("%s\"error_codes\": [", indent_level_four);
+ for (unsigned i = 0; i < device->dynamic_info.error_code_count; ++i) {
+ if (i > 0)
+ printf(", ");
+ printf("%u", device->dynamic_info.error_codes[i]);
+ }
+ printf("],\n");
+ } else {
+ printf("%s\"error_codes\": null,\n", indent_level_four);
+ }
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, driver_error_codes)) {
+ printf("%s\"driver_error_codes\": [", indent_level_four);
+ for (unsigned i = 0; i < device->dynamic_info.driver_error_code_count; ++i) {
+ if (i > 0)
+ printf(", ");
+ printf("%u", device->dynamic_info.driver_error_codes[i]);
+ }
+ printf("],\n");
+ } else {
+ printf("%s\"driver_error_codes\": null,\n", indent_level_four);
+ }
+ SNAPSHOT_COUNT("ecc_hbm_single_bit", ecc_hbm_single_bit_errors);
+ SNAPSHOT_COUNT("ecc_hbm_double_bit", ecc_hbm_double_bit_errors);
+ SNAPSHOT_COUNT("ecc_hbm_total_single_bit", ecc_hbm_total_single_bit_errors);
+ SNAPSHOT_COUNT("ecc_hbm_total_double_bit", ecc_hbm_total_double_bit_errors);
+ SNAPSHOT_COUNT("ecc_hbm_single_bit_isolated_pages", ecc_hbm_single_bit_isolated_pages);
+ SNAPSHOT_COUNT("ecc_hbm_double_bit_isolated_pages", ecc_hbm_double_bit_isolated_pages);
+ SNAPSHOT_COUNT("ecc_ddr_single_bit", ecc_ddr_single_bit_errors);
+ SNAPSHOT_COUNT("ecc_ddr_double_bit", ecc_ddr_double_bit_errors);
+ SNAPSHOT_COUNT("ecc_ddr_total_single_bit", ecc_ddr_total_single_bit_errors);
+ SNAPSHOT_COUNT("ecc_ddr_total_double_bit", ecc_ddr_total_double_bit_errors);
+ SNAPSHOT_COUNT("ecc_ddr_single_bit_isolated_pages", ecc_ddr_single_bit_isolated_pages);
+ SNAPSHOT_COUNT("ecc_ddr_double_bit_isolated_pages", ecc_ddr_double_bit_isolated_pages);
+ SNAPSHOT_COUNT("pcie_pcs_rx_errors", pcie_pcs_rx_error_count);
+ SNAPSHOT_COUNT("pcie_phy_lane_errors", pcie_phy_lane_error_count);
+ SNAPSHOT_COUNT("pcie_symbol_unlock_errors", pcie_symbol_unlock_error_count);
+ SNAPSHOT_COUNT("pcie_lcrc_errors", pcie_lcrc_error_count);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, pcie_dcrc_error_count))
+ printf("%s\"pcie_dcrc_errors\": %u,\n", indent_level_four, device->dynamic_info.pcie_dcrc_error_count);
+ else
+ printf("%s\"pcie_dcrc_errors\": null,\n", indent_level_four);
+ SNAPSHOT_COUNT("pcie_link_tx_errors", pcie_link_tx_error_count);
+ SNAPSHOT_COUNT("pcie_link_rx_errors", pcie_link_rx_error_count);
+ SNAPSHOT_COUNT("pcie_link_lcrc_errors", pcie_link_lcrc_error_count);
+ SNAPSHOT_COUNT("pcie_link_ecrc_errors", pcie_link_ecrc_error_count);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, pcie_link_retry_count))
+ printf("%s\"pcie_link_retries\": %u,\n", indent_level_four, device->dynamic_info.pcie_link_retry_count);
+ else
+ printf("%s\"pcie_link_retries\": null,\n", indent_level_four);
+
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, hccs_tx_bandwidth))
+ printf("%s\"hccs_tx_bandwidth\": \"%.3fGB/s\",\n", indent_level_four, device->dynamic_info.hccs_tx_bandwidth);
+ else
+ printf("%s\"hccs_tx_bandwidth\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, hccs_rx_bandwidth))
+ printf("%s\"hccs_rx_bandwidth\": \"%.3fGB/s\",\n", indent_level_four, device->dynamic_info.hccs_rx_bandwidth);
+ else
+ printf("%s\"hccs_rx_bandwidth\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, ub_link_status)) {
+ static const char *const ub_status_names[] = {"NO_LINK", "LINK", "PARTIAL", "NO_NEED_LINK"};
+ unsigned ub_status = device->dynamic_info.ub_link_status;
+ printf("%s\"ub_link_status\": \"%s\",\n", indent_level_four,
+ ub_status < sizeof(ub_status_names) / sizeof(ub_status_names[0]) ? ub_status_names[ub_status] : "UNKNOWN");
+ printf("%s\"ub_link_status_code\": %u,\n", indent_level_four, ub_status);
+ } else {
+ printf("%s\"ub_link_status\": null,\n", indent_level_four);
+ printf("%s\"ub_link_status_code\": null,\n", indent_level_four);
+ }
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, ub_tx_bandwidth))
+ printf("%s\"ub_tx_bandwidth\": \"%.3fMB/s\",\n", indent_level_four, device->dynamic_info.ub_tx_bandwidth);
+ else
+ printf("%s\"ub_tx_bandwidth\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, ub_rx_bandwidth))
+ printf("%s\"ub_rx_bandwidth\": \"%.3fMB/s\",\n", indent_level_four, device->dynamic_info.ub_rx_bandwidth);
+ else
+ printf("%s\"ub_rx_bandwidth\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, rdma_tx_bandwidth))
+ printf("%s\"rdma_tx_bandwidth\": \"%uMB/s\",\n", indent_level_four, device->dynamic_info.rdma_tx_bandwidth);
+ else
+ printf("%s\"rdma_tx_bandwidth\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, rdma_rx_bandwidth))
+ printf("%s\"rdma_rx_bandwidth\": \"%uMB/s\",\n", indent_level_four, device->dynamic_info.rdma_rx_bandwidth);
+ else
+ printf("%s\"rdma_rx_bandwidth\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, network_tx_packets))
+ printf("%s\"network_tx_packets\": %llu,\n", indent_level_four, device->dynamic_info.network_tx_packets);
+ else
+ printf("%s\"network_tx_packets\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, network_rx_packets))
+ printf("%s\"network_rx_packets\": %llu,\n", indent_level_four, device->dynamic_info.network_rx_packets);
+ else
+ printf("%s\"network_rx_packets\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, network_tx_bytes))
+ printf("%s\"network_tx_bytes\": %llu,\n", indent_level_four, device->dynamic_info.network_tx_bytes);
+ else
+ printf("%s\"network_tx_bytes\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, network_rx_bytes))
+ printf("%s\"network_rx_bytes\": %llu,\n", indent_level_four, device->dynamic_info.network_rx_bytes);
+ else
+ printf("%s\"network_rx_bytes\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, network_tx_errors))
+ printf("%s\"network_tx_errors\": %llu,\n", indent_level_four, device->dynamic_info.network_tx_errors);
+ else
+ printf("%s\"network_tx_errors\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, network_rx_errors))
+ printf("%s\"network_rx_errors\": %llu,\n", indent_level_four, device->dynamic_info.network_rx_errors);
+ else
+ printf("%s\"network_rx_errors\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, network_rx_fcs_errors))
+ printf("%s\"network_rx_fcs_errors\": %llu,\n", indent_level_four, device->dynamic_info.network_rx_fcs_errors);
+ else
+ printf("%s\"network_rx_fcs_errors\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, device_system_time))
+ printf("%s\"device_system_time\": %u,\n", indent_level_four, device->dynamic_info.device_system_time);
+ else
+ printf("%s\"device_system_time\": null,\n", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, ecc_hbm_history_count)) {
+ printf("%s\"ecc_hbm_history_count\": %u,\n", indent_level_four, device->dynamic_info.ecc_hbm_history_count);
+ printf("%s\"ecc_hbm_last_error_time\": %u,\n", indent_level_four, device->dynamic_info.ecc_hbm_last_error_time);
+ } else {
+ printf("%s\"ecc_hbm_history_count\": null,\n", indent_level_four);
+ printf("%s\"ecc_hbm_last_error_time\": null,\n", indent_level_four);
+ }
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, ecc_ddr_history_count)) {
+ printf("%s\"ecc_ddr_history_count\": %u,\n", indent_level_four, device->dynamic_info.ecc_ddr_history_count);
+ printf("%s\"ecc_ddr_last_error_time\": %u,\n", indent_level_four, device->dynamic_info.ecc_ddr_last_error_time);
+ } else {
+ printf("%s\"ecc_ddr_history_count\": null,\n", indent_level_four);
+ printf("%s\"ecc_ddr_last_error_time\": null,\n", indent_level_four);
+ }
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, ub_port_id)) {
+ printf("%s\"ub_port_id\": %u,\n", indent_level_four, device->dynamic_info.ub_port_id);
+ printf("%s\"ub_port_tx_packets\": %llu,\n", indent_level_four, device->dynamic_info.ub_port_tx_packets);
+ printf("%s\"ub_port_rx_packets\": %llu,\n", indent_level_four, device->dynamic_info.ub_port_rx_packets);
+ printf("%s\"ub_port_tx_errors\": %llu,\n", indent_level_four, device->dynamic_info.ub_port_tx_errors);
+ printf("%s\"ub_port_rx_errors\": %llu,\n", indent_level_four, device->dynamic_info.ub_port_rx_errors);
+ printf("%s\"ub_port_crc_errors\": %llu,\n", indent_level_four, device->dynamic_info.ub_port_crc_errors);
+ } else {
+ printf("%s\"ub_port_id\": null,\n", indent_level_four);
+ printf("%s\"ub_port_tx_packets\": null,\n", indent_level_four);
+ printf("%s\"ub_port_rx_packets\": null,\n", indent_level_four);
+ printf("%s\"ub_port_tx_errors\": null,\n", indent_level_four);
+ printf("%s\"ub_port_rx_errors\": null,\n", indent_level_four);
+ printf("%s\"ub_port_crc_errors\": null,\n", indent_level_four);
+ }
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, network_tc_stats)) {
+ printf("%s\"network_tc_tx_packets\": %llu,\n", indent_level_four, device->dynamic_info.network_tc_tx_packets);
+ printf("%s\"network_tc_rx_packets\": %llu,\n", indent_level_four, device->dynamic_info.network_tc_rx_packets);
+ } else {
+ printf("%s\"network_tc_tx_packets\": null,\n", indent_level_four);
+ printf("%s\"network_tc_rx_packets\": null,\n", indent_level_four);
+ }
+ unsigned snapshot_fault_event_count = device->dynamic_info.fault_event_count > GPUINFO_MAX_FAULT_EVENTS
+ ? GPUINFO_MAX_FAULT_EVENTS
+ : device->dynamic_info.fault_event_count;
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, fault_events)) {
+ printf("%s\"fault_events\": [", indent_level_four);
+ for (unsigned i = 0; i < snapshot_fault_event_count; ++i) {
+ if (i > 0)
+ fputs(", ", stdout);
+ printf("{\"event_id\": %u, \"severity\": %u, \"assertion\": %u, \"alarm_raised_time\": %llu, \"event_name\": ",
+ device->dynamic_info.fault_events[i].event_id, device->dynamic_info.fault_events[i].severity,
+ device->dynamic_info.fault_events[i].assertion, device->dynamic_info.fault_events[i].alarm_raised_time);
+ print_json_string(device->dynamic_info.fault_events[i].event_name);
+ fputs(", \"additional_info\": ", stdout);
+ print_json_string(device->dynamic_info.fault_events[i].additional_info);
+ fputs("}", stdout);
+ }
+ fputs("],\n", stdout);
+ } else {
+ printf("%s\"fault_events\": null,\n", indent_level_four);
+ }
+ printf("%s\"fault_event_count\": ", indent_level_four);
+ if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, fault_events))
+ printf("%u\n", snapshot_fault_event_count);
+ else
+ fputs("null\n", stdout);
+
+#undef SNAPSHOT_PERCENT
+#undef SNAPSHOT_MHZ
+#undef SNAPSHOT_TEMP
+#undef SNAPSHOT_COUNT
+#undef SNAPSHOT_STATIC_STRING
// Processes
if (hide_processes_option) {
@@ -2276,31 +2845,9 @@ void print_snapshot(struct list_head *devices, bool use_fahrenheit_option, bool
printf("%s\"pid\": \"%d\",\n", indent_level_eight, proc->pid);
if (GPUINFO_PROCESS_FIELD_VALID(proc, cmdline) && proc->cmdline) {
- printf("%s\"cmdline\": \"", indent_level_eight);
- for (char *li = proc->cmdline; *li != '\0'; li++) {
- // We need to escape some characters for for json strings
- if (*li == '\n') {
- printf("\\n");
- continue;
- } else if (*li == '\b') {
- printf("\\b");
- continue;
- } else if (*li == '\f') {
- printf("\\f");
- continue;
- } else if (*li == '\r') {
- printf("\\r");
- continue;
- } else if (*li == '\t') {
- printf("\\t");
- continue;
- }
- // escaping backslash and quotes
- if (*li == '\\' || *li == '"')
- printf("\\");
- printf("%c", *li);
- }
- printf("\",\n");
+ printf("%s\"cmdline\": ", indent_level_eight);
+ print_json_string(proc->cmdline);
+ fputs(",\n", stdout);
} else {
printf("%s\"cmdline\": null,\n", indent_level_eight);
}
@@ -2331,9 +2878,10 @@ void print_snapshot(struct list_head *devices, bool use_fahrenheit_option, bool
// GPU memory usage
printf("%s\"user\": ", indent_level_eight);
if (GPUINFO_PROCESS_FIELD_VALID(proc, user_name))
- printf("\"%s\",\n", proc->user_name);
+ print_json_string(proc->user_name);
else
- printf("null,\n");
+ fputs("null", stdout);
+ fputs(",\n", stdout);
// GPU usage
printf("%s\"gpu_usage\": ", indent_level_eight);