diff --git a/meta-facebook/gt-cc/src/platform/plat_fru.c b/meta-facebook/gt-cc/src/platform/plat_fru.c index 4c5f005361..140e3c555f 100644 --- a/meta-facebook/gt-cc/src/platform/plat_fru.c +++ b/meta-facebook/gt-cc/src/platform/plat_fru.c @@ -235,3 +235,146 @@ void pal_load_fru_config(void) { memcpy(&fru_config, &plat_fru_config, sizeof(plat_fru_config)); } + +static void decode_field(uint8_t *data, int len, char *buffer, int buffer_size) +{ + CHECK_NULL_ARG(data); + + if (len <= 0 || len >= buffer_size) { + buffer[0] = '\0'; + return; + } + + memcpy(buffer, data, len); + buffer[len] = '\0'; +} + +static bool get_nic_product_manufacturer(uint8_t fru_id, char *manufacturer, + uint8_t manufacturer_size) +{ + CHECK_NULL_ARG_WITH_RETURN(manufacturer, false); + + if (manufacturer_size == 0) { + LOG_ERR("Invalid manufacturer size: %d", manufacturer_size); + return false; + } + + EEPROM_ENTRY fru_entry; + memset(&fru_entry, 0, sizeof(fru_entry)); + + fru_entry.config = fru_config[fru_id]; + fru_entry.offset = 0; + fru_entry.data_len = 8; + + if (FRU_read(&fru_entry) != FRU_READ_SUCCESS) { + LOG_ERR("Failed to read FRU header for FRU ID %d", fru_id); + return false; + } + + // Check FRU common header format identifier + if (fru_entry.data[0] != 0x01) { + LOG_ERR("Invalid FRU format for FRU ID %d", fru_id); + return false; + } + + // Get product area offset (5th byte * 8) + uint16_t product_area_offset = fru_entry.data[4] * 8; + if (product_area_offset == 0) { + LOG_ERR("No product area found for FRU ID %d", fru_id); + return false; + } + + // Read product area header + fru_entry.offset = product_area_offset; + fru_entry.data_len = 3; + + if (FRU_read(&fru_entry) != FRU_READ_SUCCESS) { + LOG_ERR("Failed to read product area header for FRU ID %d", fru_id); + return false; + } + + // Check product area format version + if (fru_entry.data[0] != 0x01) { + LOG_ERR("Invalid product area format for FRU ID %d", fru_id); + return false; + } + + uint16_t area_len = fru_entry.data[1] * 8; + if (area_len < 4) { + LOG_ERR("Invalid product area length for FRU ID %d", fru_id); + return false; + } + + // Read the first field (product manufacturer) type/length + fru_entry.offset = product_area_offset + 3; + fru_entry.data_len = 1; + + if (FRU_read(&fru_entry) != FRU_READ_SUCCESS) { + LOG_ERR("Failed to read product manufacturer field for FRU ID %d", fru_id); + return false; + } + + uint8_t type_length = fru_entry.data[0]; + if (type_length == 0xC1) { + // End of fields marker + LOG_WRN("No product manufacturer field found for FRU ID %d", fru_id); + return false; + } + + int field_len = type_length & 0x3F; + if (field_len <= 0 || field_len >= manufacturer_size) { + LOG_ERR("Invalid product manufacturer field length for FRU ID %d", fru_id); + return false; + } + + // Read the product manufacturer field data + fru_entry.offset = product_area_offset + 4; + fru_entry.data_len = field_len; + + if (FRU_read(&fru_entry) != FRU_READ_SUCCESS) { + LOG_ERR("Failed to read product manufacturer data for FRU ID %d", fru_id); + return false; + } + + decode_field(fru_entry.data, field_len, manufacturer, manufacturer_size); + + LOG_DBG("NIC FRU ID %d product manufacturer: %s", fru_id, manufacturer); + return true; +} + +bool get_first_nic_manufacturer(char *manufacturer, uint8_t manufacturer_size) +{ + CHECK_NULL_ARG_WITH_RETURN(manufacturer, false); + + if (manufacturer_size == 0) { + LOG_ERR("Invalid manufacturer size: %d", manufacturer_size); + return false; + } + + bool found_manufacturer = false; + char temp_manufacturer[32]; + + for (uint8_t i = 0; i < NIC_MAX_NUMBER; i++) { + // Check if NIC is present (presence pin is active low) + if (gpio_get(nic_prsnt_pin[i])) { + LOG_INF("NIC%d: Not present", i); + continue; + } + + if (get_nic_product_manufacturer(NIC0_FRU_ID + i, temp_manufacturer, + sizeof(temp_manufacturer))) { + LOG_INF("NIC%d: Product Manufacturer = %s", i, temp_manufacturer); + + // If this is the first manufacturer found, save it + if (!found_manufacturer) { + strncpy(manufacturer, temp_manufacturer, manufacturer_size - 1); + manufacturer[manufacturer_size - 1] = '\0'; + found_manufacturer = true; + } + } else { + LOG_INF("NIC%d: Failed to read product manufacturer", i); + } + } + + return found_manufacturer; +} diff --git a/meta-facebook/gt-cc/src/platform/plat_fru.h b/meta-facebook/gt-cc/src/platform/plat_fru.h index 1f4eaf8900..95d4f0147f 100644 --- a/meta-facebook/gt-cc/src/platform/plat_fru.h +++ b/meta-facebook/gt-cc/src/platform/plat_fru.h @@ -63,6 +63,14 @@ enum GT_NIC_CONFIG { #define NIC6_FRU_PORT 0x0C #define NIC7_FRU_PORT 0x0D +typedef struct { + char product_manufacturer[32]; + char product_name[32]; + char product_part_number[32]; + char product_version[32]; +} ProductInfo; + uint8_t check_nic_type_by_fru(); +bool get_first_nic_manufacturer(char *manufacturer, uint8_t manufacturer_size); #endif diff --git a/meta-facebook/gt-cc/src/platform/plat_mctp.c b/meta-facebook/gt-cc/src/platform/plat_mctp.c index f6c9af4835..50f22f926c 100644 --- a/meta-facebook/gt-cc/src/platform/plat_mctp.c +++ b/meta-facebook/gt-cc/src/platform/plat_mctp.c @@ -65,6 +65,9 @@ LOG_MODULE_REGISTER(plat_mctp); #define MCTP_EID_NIC_6 0x16 #define MCTP_EID_NIC_7 0x17 +#define NVIDIA_NIC_MANUFACTURER "Nvidia" +#define BROADCOM_NIC_MANUFACTURER "Broadcom" + static uint8_t nic_config = NIC_CONFIG_UNKNOWN; K_TIMER_DEFINE(send_cmd_timer, send_cmd_to_dev, NULL); @@ -501,26 +504,32 @@ bool is_broadcom_thor2_nic_type() return is_broadcom_thor2_nic; } -void check_nic_config_by_ncsi(void) +void check_nic_config(void) { + char nic_manufacturer[32]; + + bool found = get_first_nic_manufacturer(nic_manufacturer, sizeof(nic_manufacturer)); + + if (found) { + LOG_INF("First NIC manufacturer found: %s", nic_manufacturer); + } else { + LOG_INF("No NIC manufacturer found"); + } + uint8_t config = NIC_CONFIG_UNKNOWN; - if (is_broadcom_thor2_nic_type() == true) { + if (strncmp(nic_manufacturer, NVIDIA_NIC_MANUFACTURER, + sizeof(NVIDIA_NIC_MANUFACTURER) - 1) == 0) { + LOG_INF("NVIDIA NIC detected"); + config = mellanox_cx7_ncsi_get_link_type(); + } else if (strncmp(nic_manufacturer, BROADCOM_NIC_MANUFACTURER, + sizeof(BROADCOM_NIC_MANUFACTURER) - 1) == 0) { + LOG_INF("Broadcom NIC detected"); set_cx7_init_arg_to_thor2(); config = NIC_CONFIG_THOR2; } else { - // set_cx7_init_arg_to_cx7(); - config = mellanox_cx7_ncsi_get_link_type(); + LOG_INF("Unknown NIC manufacturer: %s", nic_manufacturer); } - // config = mellanox_cx7_ncsi_get_link_type(); - - /* Remove this process for short term fix, will add back to support BMC get thor 2 type in the future */ - /* Double check by fru if config is not IB_CX7 */ - // if (config == NIC_CONFIG_CX7 || config == NIC_CONFIG_UNKNOWN) { - // LOG_INF("Double check nic type by fru"); - // config = check_nic_type_by_fru(); - // } - nic_config = config; LOG_INF("NIC config is %d, 0: UNKNOWN, 1: CX7, 2: IB_CX7, 3: THOR2", nic_config); } @@ -536,7 +545,7 @@ void send_cmd_to_dev_handler(struct k_work *work) set_dev_endpoint(); /* check nic config by ncsi */ - check_nic_config_by_ncsi(); + check_nic_config(); /* init mellanox cx7 ncsi */ if ((nic_config == NIC_CONFIG_IB_CX7) || (nic_config == NIC_CONFIG_CX7))