meta-facebook/meta-fby3/recipes-fby3/plat-utils/files/enclosure-util/enclosure-util.c (549 lines of code) (raw):

/* * enclosure-util * Copyright 2015-present Facebook. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <signal.h> #include <syslog.h> #include <string.h> #include <openbmc/nvme-mi.h> #include <openbmc/pal.h> #include <facebook/fby3_common.h> #define CMD_DRIVE_STATUS 0 #define CMD_DRIVE_HEALTH 1 #define NVME_BAD_HEALTH 1 #define NVME_SFLGS_MASK_BIT 0x28 // check bit 5,3 #define NVME_SMART_WARNING_MASK_BIT 0x1F // check bit 0~4 #define MAX_SERIAL_NUM 20 #define SPE_SSD_NUM 6 #define MAX_PART_NUM 40 char path[64] = {0}; int fd; static uint8_t m_slot_id = 0; static uint8_t type_2ou = UNKNOWN_BOARD; static void print_usage_help(void) { printf("Usage: enclosure-util <slot1|slot2|slot3|slot4> --drive-status <all|1U-dev[0..3]|2U-dev[0..13]>\n"); printf(" enclosure-util <slot1|slot2|slot3|slot4> --drive-health\n"); if ( pal_is_exp() == PAL_EOK ) { printf("Usage: enclosure-util <slot1-2U-top|slot1-2U-bot> --drive-status <all|2U-dev[0..13]>\n"); printf(" enclosure-util <slot1-2U-top|slot1-2U-bot> --drive-health\n"); } } static int ssd_monitor_enable(uint8_t slot_id, uint8_t intf, bool enable) { int ret = 0; ret = bic_enable_ssd_sensor_monitor(slot_id, enable, intf); if ( enable == false ) { msleep(100); } return ret; } static int drive_status(ssd_data *ssd) { t_status_flags status_flag_decoding; t_smart_warning smart_warning_decoding; t_key_value_pair temp_decoding; t_key_value_pair pdlu_decoding; t_key_value_pair vendor_decoding; t_key_value_pair sn_decoding; t_key_value_pair pn_decoding; t_key_value_pair meff_decoding; t_key_value_pair ffi_0_decoding; t_key_value_pair sinfo_0_decoding; t_key_value_pair module_helath_decoding; t_key_value_pair lower_thermal_temp_decoding; t_key_value_pair upper_thermal_temp_decoding; t_key_value_pair power_state_decoding; t_key_value_pair i2c_freq_decoding; t_key_value_pair tdp_level_decoding; t_key_value_pair asic_version_decoding; t_key_value_pair fw_version_decoding; t_key_value_pair asic_core_vol1_decoding; t_key_value_pair asic_core_vol2_decoding; t_key_value_pair power_rail_vol1_decoding; t_key_value_pair power_rail_vol2_decoding; t_key_value_pair asic_error_type_decoding; t_key_value_pair module_error_type_decoding; t_key_value_pair warning_flag_decoding; t_key_value_pair interrupt_flag_decoding; t_key_value_pair max_asic_temp_decoding; t_key_value_pair total_int_mem_err_count_decoding; t_key_value_pair total_ext_mem_err_count_decoding; t_key_value_pair smbus_err_decoding; printf("\n"); nvme_sflgs_decode(ssd->sflgs, &status_flag_decoding); printf("%s: %s\n", status_flag_decoding.self.key, status_flag_decoding.self.value); printf(" %s: %s\n", status_flag_decoding.read_complete.key, status_flag_decoding.read_complete.value); printf(" %s: %s\n", status_flag_decoding.ready.key, status_flag_decoding.ready.value); printf(" %s: %s\n", status_flag_decoding.functional.key, status_flag_decoding.functional.value); printf(" %s: %s\n", status_flag_decoding.reset_required.key, status_flag_decoding.reset_required.value); printf(" %s: %s\n", status_flag_decoding.port0_link.key, status_flag_decoding.port0_link.value); printf(" %s: %s\n", status_flag_decoding.port1_link.key, status_flag_decoding.port1_link.value); nvme_smart_warning_decode(ssd->warning, &smart_warning_decoding); printf("%s: %s\n", smart_warning_decoding.self.key, smart_warning_decoding.self.value); printf(" %s: %s\n", smart_warning_decoding.spare_space.key, smart_warning_decoding.spare_space.value); printf(" %s: %s\n", smart_warning_decoding.temp_warning.key, smart_warning_decoding.temp_warning.value); printf(" %s: %s\n", smart_warning_decoding.reliability.key, smart_warning_decoding.reliability.value); printf(" %s: %s\n", smart_warning_decoding.media_status.key, smart_warning_decoding.media_status.value); printf(" %s: %s\n", smart_warning_decoding.backup_device.key, smart_warning_decoding.backup_device.value); nvme_temp_decode(ssd->temp, &temp_decoding); printf("%s: %s\n", temp_decoding.key, temp_decoding.value); nvme_pdlu_decode(ssd->pdlu, &pdlu_decoding); printf("%s: %s\n", pdlu_decoding.key, pdlu_decoding.value); nvme_vendor_decode(ssd->vendor, &vendor_decoding); printf("%s: %s\n", vendor_decoding.key, vendor_decoding.value); nvme_serial_num_decode(ssd->serial_num, &sn_decoding); printf("%s: %s\n", sn_decoding.key, sn_decoding.value); if (ssd->fb_defined == 0x01) { nvme_part_num_decode(ssd->block_len_module_id_area, ssd->part_num, &pn_decoding); printf("%s: %s\n", pn_decoding.key, pn_decoding.value); nvme_meff_decode(ssd->block_len_module_id_area, ssd->meff, &meff_decoding); printf("%s: %s\n", meff_decoding.key, meff_decoding.value); nvme_ffi_0_decode(ssd->block_len_module_id_area, ssd->ffi_0, &ffi_0_decoding); printf("%s: %s\n", ffi_0_decoding.key, ffi_0_decoding.value); if (ssd->ffi_0 == FFI_0_ACCELERATOR) { nvme_raw_data_prase("Module health", ssd->block_len_module_stat_area, ssd->module_helath, &module_helath_decoding); printf("%s: %s\n", module_helath_decoding.key, module_helath_decoding.value); nvme_lower_threshold_temp_decode(ssd->block_len_module_stat_area, ssd->lower_theshold, &lower_thermal_temp_decoding); printf("%s: %s\n", lower_thermal_temp_decoding.key, lower_thermal_temp_decoding.value); nvme_upper_threshold_temp_decode(ssd->block_len_module_stat_area, ssd->upper_threshold, &upper_thermal_temp_decoding); printf("%s: %s\n", upper_thermal_temp_decoding.key, upper_thermal_temp_decoding.value); nvme_power_state_decode(ssd->block_len_module_stat_area, ssd->power_state, &power_state_decoding); printf("%s: %s\n", power_state_decoding.key, power_state_decoding.value); nvme_i2c_freq_decode (ssd->block_len_module_stat_area, ssd->i2c_freq, &i2c_freq_decoding); printf("%s: %s\n", i2c_freq_decoding.key, i2c_freq_decoding.value); nvme_tdp_level_decode (ssd->block_len_module_stat_area, ssd->tdp_level, &tdp_level_decoding); printf("%s: %s\n", tdp_level_decoding.key, tdp_level_decoding.value); nvme_raw_data_prase("ASIC version", ssd->block_len_ver_area, ssd->asic_version, &asic_version_decoding); printf("%s: %s\n", asic_version_decoding.key, asic_version_decoding.value); nvme_fw_version_decode(ssd->block_len_ver_area, ssd->fw_major_ver, ssd->fw_minor_ver, &fw_version_decoding); printf("%s: %s\n", fw_version_decoding.key, fw_version_decoding.value); nvme_monitor_area_decode("ASIC Core1 Voltage", ssd->block_len_mon_area, ssd->asic_core_vol1, ASIC_CORE_VOL_UNIT, &asic_core_vol1_decoding); printf("%s: %s\n", asic_core_vol1_decoding.key, asic_core_vol1_decoding.value); nvme_monitor_area_decode("ASIC Core2 Voltage", ssd->block_len_mon_area, ssd->asic_core_vol2, ASIC_CORE_VOL_UNIT, &asic_core_vol2_decoding); printf("%s: %s\n", asic_core_vol2_decoding.key, asic_core_vol2_decoding.value); nvme_monitor_area_decode("Module Power Rail1 Voltage", ssd->block_len_mon_area, ssd->power_rail_vol1, POWER_RAIL_VOL_UNIT, &power_rail_vol1_decoding); printf("%s: %s\n", power_rail_vol1_decoding.key, power_rail_vol1_decoding.value); nvme_monitor_area_decode("Module Power Rail2 Voltage", ssd->block_len_mon_area, ssd->power_rail_vol2, POWER_RAIL_VOL_UNIT, &power_rail_vol2_decoding); printf("%s: %s\n", power_rail_vol2_decoding.key, power_rail_vol2_decoding.value); nvme_raw_data_prase("ASIC Error Type Report", ssd->block_len_err_ret_area, ssd->asic_error_type, &asic_error_type_decoding); printf("%s: %s\n", asic_error_type_decoding.key, asic_error_type_decoding.value); nvme_raw_data_prase("Module Error Type Report", ssd->block_len_err_ret_area, ssd->module_error_type, &module_error_type_decoding); printf("%s: %s\n", module_error_type_decoding.key, module_error_type_decoding.value); nvme_raw_data_prase("Warning Flag", ssd->block_len_err_ret_area, ssd->warning_flag, &warning_flag_decoding); printf("%s: %s\n", warning_flag_decoding.key, warning_flag_decoding.value); nvme_raw_data_prase("Interrupt Flag", ssd->block_len_err_ret_area, ssd->interrupt_flag, &interrupt_flag_decoding); printf("%s: %s\n", interrupt_flag_decoding.key, interrupt_flag_decoding.value); nvme_max_asic_temp_decode(ssd->block_len_err_ret_area, ssd->max_asic_temp, &max_asic_temp_decoding); printf("%s: %s\n", max_asic_temp_decoding.key, max_asic_temp_decoding.value); nvme_total_int_mem_err_count_decode(ssd->block_len_err_ret_area, ssd->total_int_mem_err_count, &total_int_mem_err_count_decoding); printf("%s: %s\n", total_int_mem_err_count_decoding.key, total_int_mem_err_count_decoding.value); nvme_total_ext_mem_err_count_decode(ssd->block_len_err_ret_area, ssd->total_ext_mem_err_count, &total_ext_mem_err_count_decoding); printf("%s: %s\n", total_ext_mem_err_count_decoding.key, total_ext_mem_err_count_decoding.value); nvme_smbus_err_decode(ssd->block_len_err_ret_area, ssd->smbus_err, &smbus_err_decoding); printf("%s: %s\n", smbus_err_decoding.key, smbus_err_decoding.value); } else if (ssd->ffi_0 == FFI_0_STORAGE) { printf("%s: 0x%02X\n", "Storage version", ssd->ssd_ver); printf("%s: %d GB\n", "Storage Capacity", ssd->ssd_capacity); printf("%s: %d W\n", "Storage Power", ssd->ssd_pwr); nvme_sinfo_0_decode (ssd->ssd_sinfo_0,&sinfo_0_decoding); printf("%s: %s\n", sinfo_0_decoding.key, sinfo_0_decoding.value); } } return 0; } static int drive_health(ssd_data *ssd) { if ( type_2ou != GPV3_MCHP_BOARD && type_2ou != GPV3_BRCM_BOARD && type_2ou != CWC_MCHP_BOARD ) { // Not GPv3 // since accelerator doesn't implement SMART WARNING, do not check it. if ((ssd->warning & NVME_SMART_WARNING_MASK_BIT) != NVME_SMART_WARNING_MASK_BIT) return NVME_BAD_HEALTH; } if ((ssd->sflgs & NVME_SFLGS_MASK_BIT) != NVME_SFLGS_MASK_BIT) return NVME_BAD_HEALTH; return 0; } static int get_mapping_parameter(uint8_t device_id, uint8_t type_1ou, uint8_t *bus, uint8_t *intf, uint8_t *mux) { const uint8_t INTF[] = { 0, // N/A FEXP_BIC_INTF, // DEV_ID0_1OU FEXP_BIC_INTF, // DEV_ID1_1OU FEXP_BIC_INTF, // DEV_ID2_1OU FEXP_BIC_INTF, // DEV_ID3_1OU REXP_BIC_INTF, // DEV_ID0_2OU REXP_BIC_INTF, // DEV_ID1_2OU REXP_BIC_INTF, // DEV_ID2_2OU REXP_BIC_INTF, // DEV_ID3_2OU REXP_BIC_INTF, // DEV_ID4_2OU REXP_BIC_INTF // DEV_ID5_2OU }; // M.2 1OU device -> 3 2 1 0 // E1S 1OU device -> 0 1 2 3 const uint8_t BUS_EDSFF1U[] = { 0, 6, 4, 3, 2, 0, 0, 0, 0, 0, 0}; const uint8_t BUS_1OU_2OU[] = { 0, 2, 2, 4, 4, 2, 2, 4, 4, 6, 6}; const uint8_t MUX_1OU_2OU[] = { 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; *intf = INTF[device_id]; if (type_1ou == EDSFF_1U) { *bus = BUS_EDSFF1U[device_id]; } else { *bus = BUS_1OU_2OU[device_id]; *mux = MUX_1OU_2OU[device_id]; } return 0; } static int read_nvme_data(uint8_t fru_id, uint8_t slot_id, uint8_t device_id, uint8_t cmd) { int ret = 0; int offset_base = 0; char str[32]; uint8_t type_1ou = 0; uint8_t intf = 0; uint8_t mux = 0; uint8_t bus = 0; uint8_t tbuf[8] = {0}; uint8_t rbuf[64] = {0}; uint8_t tlen = 0; uint8_t rlen = 0; float tdp_val = 0; static const uint8_t spe_ssd_bus[SPE_SSD_NUM] = {2, 3, 4, 5, 6, 7}; ssd_data ssd; memset(&ssd, 0x00, sizeof(ssd_data)); //prevent the invalid access if ( type_2ou != GPV3_MCHP_BOARD && type_2ou != GPV3_BRCM_BOARD && type_2ou != E1S_BOARD && type_2ou != CWC_MCHP_BOARD ) { bic_get_1ou_type(slot_id, &type_1ou); get_mapping_parameter(device_id, type_1ou, &bus, &intf, &mux); } fby3_common_dev_name(device_id, str); if (type_2ou == E1S_BOARD) { bus = spe_ssd_bus[device_id - DEV_ID0_2OU]; intf = REXP_BIC_INTF; } else if ( type_2ou == GPV3_MCHP_BOARD || type_2ou == GPV3_BRCM_BOARD ) { // mux select ret = pal_gpv3_mux_select(slot_id, device_id); if (ret) { return ret; // fail to select mux } bus = get_gpv3_bus_number(device_id); intf = REXP_BIC_INTF; } else if ( type_2ou == CWC_MCHP_BOARD ) { ret = pal_gpv3_mux_select(fru_id, device_id); if (ret) { return ret; } bus = get_gpv3_bus_number(device_id); if (fru_id == FRU_2U_TOP) { intf = RREXP_BIC_INTF1; } else if (fru_id == FRU_2U_BOT) { intf = RREXP_BIC_INTF2; } } else if (type_1ou != EDSFF_1U) { // E1S no need but 1/2OU need to stop sensor monitor then switch mux tbuf[0] = (bus << 1) + 1; tbuf[1] = 0x02; // mux address tbuf[2] = 0; // read back 8 bytes tbuf[3] = 0x00; // offset 00 tbuf[4] = mux; tlen = 5; ret = bic_ipmb_send(slot_id, NETFN_APP_REQ, CMD_APP_MASTER_WRITE_READ, tbuf, tlen, rbuf, &rlen, intf); if (ret != 0) { printf("slot%u-%s : %s\n", slot_id, str, "NA"); syslog(LOG_DEBUG, "%s(): bic_ipmb_send offset=%d read length=%d failed", __func__,tbuf[3],rlen); return -1; } } if (cmd == CMD_DRIVE_STATUS) { printf("slot%u-%s : ", slot_id, str); do { tbuf[0] = (bus << 1) + 1; tbuf[1] = 0xD4; tbuf[2] = 8; //read back 8 bytes tbuf[3] = 0x00; // offset 00 tlen = 4; ret = bic_ipmb_send(slot_id, NETFN_APP_REQ, CMD_APP_MASTER_WRITE_READ, tbuf, tlen, rbuf, &rlen, intf); if (ret != 0) { syslog(LOG_DEBUG, "%s(): bic_ipmb_send offset=%d read length=%d failed", __func__,tbuf[3],rlen); printf("NA"); break; } ssd.sflgs = rbuf[offset_base + 1]; ssd.warning = rbuf[offset_base + 2]; ssd.temp = rbuf[offset_base + 3]; ssd.pdlu = rbuf[offset_base + 4]; tbuf[2] = 24 + offset_base;; // read back 24 bytes tbuf[3] = 0x08; // offset 08 ret = bic_ipmb_send(slot_id, NETFN_APP_REQ, CMD_APP_MASTER_WRITE_READ, tbuf, tlen, rbuf, &rlen, intf); if (ret != 0) { syslog(LOG_DEBUG, "%s(): bic_ipmb_send offset=%d read length=%d failed", __func__,tbuf[3],rlen); printf("NA"); break; } ssd.vendor = (rbuf[offset_base + 1] << 8) | rbuf[offset_base + 2]; memcpy(ssd.serial_num, &rbuf[offset_base + 3], MAX_SERIAL_NUM); if ( type_2ou == GPV3_MCHP_BOARD || type_2ou == GPV3_BRCM_BOARD || type_2ou == CWC_MCHP_BOARD ) { tbuf[2] = 55; //read back tbuf[3] = 0x20; // offset 32 ret = bic_ipmb_send(slot_id, NETFN_APP_REQ, CMD_APP_MASTER_WRITE_READ, tbuf, tlen, rbuf, &rlen, intf); if (ret != 0) { syslog(LOG_DEBUG, "%s(): bic_ipmb_send offset=%d read length=%d failed", __func__,tbuf[3],rlen); break; } ssd.block_len_module_id_area = rbuf[offset_base + 0]; ssd.fb_defined = rbuf[offset_base + 1]; memcpy(ssd.part_num, &rbuf[offset_base + 2], MAX_PART_NUM); ssd.meff = rbuf[offset_base + 42]; ssd.ffi_0 = rbuf[offset_base + 43]; if (ssd.fb_defined == 1) { if (ssd.ffi_0 == FFI_0_ACCELERATOR) { tbuf[2] = 8; //read back tbuf[3] = 0x60; // offset 96 ret = bic_ipmb_send(slot_id, NETFN_APP_REQ, CMD_APP_MASTER_WRITE_READ, tbuf, tlen, rbuf, &rlen, intf); if (ret != 0) { syslog(LOG_DEBUG, "%s(): bic_ipmb_send offset=%d read length=%d failed", __func__,tbuf[3],rlen); break; } ssd.block_len_module_stat_area = rbuf[offset_base + 0]; ssd.module_helath = rbuf[offset_base + 1]; ssd.lower_theshold = rbuf[offset_base + 2]; ssd.upper_threshold = rbuf[offset_base + 3]; ssd.power_state = rbuf[offset_base + 4]; ssd.i2c_freq = rbuf[offset_base + 5]; // Formula provided by SPH if (ssd.vendor == VENDOR_ID_INTEL) { tdp_val = rbuf[offset_base + 7] + rbuf[offset_base + 6] / 250; if (tdp_val > 13) { ssd.tdp_level = TDP_LEVEL3; } else if (tdp_val >= 10.5) { ssd.tdp_level = TDP_LEVEL2; } else { ssd.tdp_level = TDP_LEVEL1; } } else { ssd.tdp_level = rbuf[offset_base + 6]; } tbuf[2] = 8; //read back tbuf[3] = 0x68; // offset 104 ret = bic_ipmb_send(slot_id, NETFN_APP_REQ, CMD_APP_MASTER_WRITE_READ, tbuf, tlen, rbuf, &rlen, intf); if (ret != 0) { syslog(LOG_DEBUG, "%s(): bic_ipmb_send offset=%d read length=%d failed", __func__,tbuf[3],rlen); break; } ssd.block_len_ver_area = rbuf[offset_base + 0]; ssd.asic_version = rbuf[offset_base + 1]; ssd.fw_major_ver = rbuf[offset_base + 2]; ssd.fw_minor_ver = rbuf[offset_base + 3]; tbuf[2] = 10; //read back tbuf[3] = 0x70; // offset 112 ret = bic_ipmb_send(slot_id, NETFN_APP_REQ, CMD_APP_MASTER_WRITE_READ, tbuf, tlen, rbuf, &rlen, intf); if (ret != 0) { syslog(LOG_DEBUG, "%s(): bic_ipmb_send offset=%d read length=%d failed", __func__,tbuf[3],rlen); break; } ssd.block_len_mon_area = rbuf[offset_base + 0]; ssd.asic_core_vol1 = (rbuf[offset_base + 1] << 8) | rbuf[offset_base + 2]; ssd.asic_core_vol2 = (rbuf[offset_base + 3] << 8) | rbuf[offset_base + 4]; ssd.power_rail_vol1 = (rbuf[offset_base + 5] << 8) | rbuf[offset_base + 6]; ssd.power_rail_vol2 = (rbuf[offset_base + 7] << 8) | rbuf[offset_base + 8]; tbuf[2] = 10; //read back if (ssd.vendor == VENDOR_ID_BROARDCOM) { tbuf[3] = 0x84; // offset 132 } else { tbuf[3] = 0x7A; // offset 122 } ret = bic_ipmb_send(slot_id, NETFN_APP_REQ, CMD_APP_MASTER_WRITE_READ, tbuf, tlen, rbuf, &rlen, intf); if (ret != 0) { syslog(LOG_DEBUG, "%s(): bic_ipmb_send offset=%d read length=%d failed", __func__,tbuf[3],rlen); break; } ssd.block_len_err_ret_area = rbuf[offset_base + 0]; ssd.asic_error_type = rbuf[offset_base + 1]; ssd.module_error_type = rbuf[offset_base + 2]; ssd.warning_flag = rbuf[offset_base + 3]; ssd.interrupt_flag = rbuf[offset_base + 4]; ssd.max_asic_temp = rbuf[offset_base + 5]; ssd.total_int_mem_err_count = rbuf[offset_base + 6]; ssd.total_ext_mem_err_count = rbuf[offset_base + 7]; ssd.smbus_err = rbuf[offset_base + 8]; } else if (ssd.ffi_0 == FFI_0_STORAGE) { tbuf[2] = 9; //read back tbuf[3] = 0x57; // offset 87 ret = bic_ipmb_send(slot_id, NETFN_APP_REQ, CMD_APP_MASTER_WRITE_READ, tbuf, tlen, rbuf, &rlen, intf); if (ret != 0) { syslog(LOG_DEBUG, "%s(): bic_ipmb_send offset=%d read length=%d failed", __func__,tbuf[3],rlen); break; } ssd.ssd_ver = rbuf[1]; ssd.ssd_capacity = (rbuf[2] << 8) | rbuf[3]; ssd.ssd_pwr = rbuf[4]; ssd.ssd_sinfo_0 = rbuf[5]; } } } drive_status(&ssd); } while (0); printf("\n"); } else if (cmd == CMD_DRIVE_HEALTH) { tbuf[0] = (bus << 1) + 1; tbuf[1] = 0xD4; tbuf[2] = 0x08; // read back 8 bytes tbuf[3] = 0x00; // offset 00 tlen = 4; ret = bic_ipmb_send(slot_id, NETFN_APP_REQ, CMD_APP_MASTER_WRITE_READ, tbuf, tlen, rbuf, &rlen, intf); if (ret != 0) { printf("slot%u-%s : %s\n", slot_id, str, "NA"); return 0; } ssd.sflgs = rbuf[1]; ssd.warning = rbuf[2]; ret = drive_health(&ssd); // ret 1: Abnormal 0:Normal printf("slot%u-%s : %s\n", slot_id, str, (ret == 0)?"Normal":"Abnormal"); } else { printf("%s(): unknown cmd \n", __func__); return -1; } return 0; } static void enclosure_sig_handler(int sig) { if ( type_2ou == GPV3_MCHP_BOARD || type_2ou == GPV3_BRCM_BOARD ) { // Config C or Config D GPv3 if ( ssd_monitor_enable(m_slot_id, REXP_BIC_INTF, true) < 0 ) { printf("err: failed to enable SSD monitoring"); } } else if (type_2ou == CWC_MCHP_BOARD) { if ( ssd_monitor_enable(m_slot_id, RREXP_BIC_INTF1, true) < 0 ) { printf("err: failed to enable 2U-top SSD monitoring"); } if ( ssd_monitor_enable(m_slot_id, RREXP_BIC_INTF2, true) < 0 ) { printf("err: failed to enable 2U-bot SSD monitoring"); } } if (flock(fd, LOCK_UN)) { syslog(LOG_WARNING, "%s: failed to unflock on %s", __func__, path); } close(fd); remove(path); } int main(int argc, char **argv) { int ret; int present = 0; uint8_t fru_id = 0; uint8_t slot_id = 0; uint8_t dev_id = 0; uint8_t device_start = 0, device_end = 0; uint8_t is_slot_present = 0; struct sigaction sa; uint8_t intf = 0; if (argc != 3 && argc != 4) { print_usage_help(); return -1; } ret = pal_get_fru_id(argv[1], &fru_id); if (ret < 0) { printf("Wrong fru: %s\n", argv[1]); print_usage_help(); return -1; } if ( fru_id == FRU_2U_TOP ) { intf = RREXP_BIC_INTF1; } else if ( fru_id == FRU_2U_BOT ) { intf = RREXP_BIC_INTF2; } else { intf = REXP_BIC_INTF; } pal_get_fru_slot(fru_id, &slot_id); m_slot_id = slot_id; // need to check slot present ret = pal_is_fru_prsnt(fru_id, &is_slot_present); if (ret < 0 || is_slot_present == 0) { printf("%s is not present!\n", argv[1]); return -1; } sa.sa_handler = enclosure_sig_handler; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGHUP, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGQUIT, &sa, NULL); sigaction(SIGSEGV, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sprintf(path, SLOT_SENSOR_LOCK, slot_id); fd = open(path, O_CREAT | O_RDWR, 0666); ret = flock(fd, LOCK_EX | LOCK_NB); if (ret) { if(EWOULDBLOCK == errno) { printf("the lock file is already using, please wait \n"); return -1; } } // check 1/2OU present status ret = bic_is_m2_exp_prsnt(slot_id); if ( ret < 0 ) { printf("%s() Cannot get the m2 prsnt status\n", __func__); goto exit; } present = (uint8_t)ret; if ( (present & PRESENT_2OU) == PRESENT_2OU ) { if ( fby3_common_get_2ou_board_type(slot_id, &type_2ou) < 0) { printf("Failed to get slot%d 2ou board type\n",type_2ou); goto exit; } } if ( type_2ou == GPV3_MCHP_BOARD || type_2ou == GPV3_BRCM_BOARD || type_2ou == CWC_MCHP_BOARD ) { // Config C or Config D GPv3 device_start = DEV_ID0_2OU; device_end = DEV_ID13_2OU; if ( ssd_monitor_enable(slot_id, intf, false) < 0 ) { printf("err: failed to disable SSD monitoring\n"); goto exit; } } else if ( type_2ou == E1S_BOARD ) { device_start = DEV_ID0_2OU; device_end = DEV_ID5_2OU; } else if ( type_2ou == DP_RISER_BOARD ) { printf("DP not support \n"); goto exit; } else if ( present == PRESENT_1OU ) { device_start = DEV_ID0_1OU; device_end = DEV_ID3_1OU; } else if ( present == PRESENT_2OU ) { device_start = DEV_ID0_2OU; device_end = DEV_ID5_2OU; } else if ( present == (PRESENT_1OU + PRESENT_2OU) ) { device_start = DEV_ID0_1OU; device_end = DEV_ID5_2OU; } else { printf("Please check the board config \n"); goto exit; } if ((argc == 4) && !strcmp(argv[2], "--drive-status")) { if (!strcmp(argv[3], "all")) { for (int i = device_start; i <= device_end; i++) { read_nvme_data(fru_id, slot_id, i, CMD_DRIVE_STATUS); } } else { ret = pal_get_dev_id(argv[3], &dev_id); if (ret < 0) { printf("pal_get_dev_id failed for %s %s\n", argv[1], argv[3]); print_usage_help(); goto exit; } if ((dev_id < device_start) || (dev_id > device_end)) { printf("Please check the board config \n"); goto exit; } read_nvme_data(fru_id, slot_id, dev_id, CMD_DRIVE_STATUS); } } else if ((argc == 3) && !strcmp(argv[2], "--drive-health")) { for (int i = device_start; i <= device_end; i++) { read_nvme_data(fru_id, slot_id, i, CMD_DRIVE_HEALTH); } } else { print_usage_help(); goto exit; } exit: if ( type_2ou == GPV3_MCHP_BOARD || type_2ou == GPV3_BRCM_BOARD || type_2ou == CWC_MCHP_BOARD ) { // Config C or Config D GPv3 if ( ssd_monitor_enable(slot_id, intf, true) < 0 ) { printf("err: failed to enable SSD monitoring"); } } ret = flock(fd, LOCK_UN); if (ret != 0) { syslog(LOG_WARNING, "%s: failed to unflock on %s", __func__, path); } close(fd); remove(path); return 0; }