From abe596145276ef0c0bd6496df3c787e76a12515a Mon Sep 17 00:00:00 2001 From: Andre Marin Date: Tue, 9 Aug 2016 15:06:58 -0500 Subject: Add FW/Cronus VPD integration Fixed FAPI_ASSERT bug in p9_get_mem_vpd_keyword.C Updated VPD binary from Chris to support all freqs Edited eff_config to match expected API vpd_info to be filled in completely. Edited ekb_ci_p9_full_cnfg to take VPD path Change-Id: I755d3121dbb058470a7693aeb8f46bceb502858b Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/29298 Tested-by: Jenkins Server Reviewed-by: Brian R. Silver Reviewed-by: Steven B. Janssen Tested-by: Hostboot CI Reviewed-by: JACOB L. HARVEY Reviewed-by: Jennifer A. Stofer Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/29530 Tested-by: FSP CI Jenkins Reviewed-by: Daniel M. Crowell --- .../hwp/accessors/p9_get_mem_vpd_keyword.C | 29 ++-- .../hwp/memory/lib/eff_config/eff_config.C | 181 +++++++++++---------- 2 files changed, 111 insertions(+), 99 deletions(-) (limited to 'src/import') diff --git a/src/import/chips/p9/procedures/hwp/accessors/p9_get_mem_vpd_keyword.C b/src/import/chips/p9/procedures/hwp/accessors/p9_get_mem_vpd_keyword.C index af72417c1..a1ce17203 100644 --- a/src/import/chips/p9/procedures/hwp/accessors/p9_get_mem_vpd_keyword.C +++ b/src/import/chips/p9/procedures/hwp/accessors/p9_get_mem_vpd_keyword.C @@ -389,20 +389,21 @@ extern "C" "No match in mapping table"); //Was a valid keyword name found? - FAPI_ASSERT(MAPPING_LAYOUT_INVALID != l_second, - fapi2::GET_MEM_VPD_UNSUPPORTED_CONFIGURATION(). - set_MCS(fapi2::ATTR_MEMVPD_POS_Type(l_mcsPos)). - set_FREQ(uint32_t(i_vpd_info.iv_freq_mhz)). - set_DIMM0RANK(uint64_t(i_vpd_info.iv_rank_count_dimm_0)). - set_DIMM1RANK(uint64_t(i_vpd_info.iv_rank_count_dimm_1)). - set_VPDMCSMASK(uint16_t(((l_mapping[l_index].mcsMaskMSB) << 8) | - l_mapping[l_index].mcsMaskLSB)). - set_VPDFREQMASK(uint8_t(l_mapping[l_index].freqMask)). - set_VPDRANKMASK(uint8_t(((l_mapping[l_index].rankMaskMSB) << 8) | - l_mapping[l_index].rankMaskLSB)). - set_TARGET(i_target). - set_VPDTYPE(i_vpd_info.iv_vpd_type), - "Unsupported configuration"); + // Cast needed due to implicit int of enums + FAPI_ASSERT( static_cast(MAPPING_LAYOUT_INVALID) != l_second, + fapi2::GET_MEM_VPD_UNSUPPORTED_CONFIGURATION(). + set_MCS(fapi2::ATTR_MEMVPD_POS_Type(l_mcsPos)). + set_FREQ(uint32_t(i_vpd_info.iv_freq_mhz)). + set_DIMM0RANK(uint64_t(i_vpd_info.iv_rank_count_dimm_0)). + set_DIMM1RANK(uint64_t(i_vpd_info.iv_rank_count_dimm_1)). + set_VPDMCSMASK(uint16_t(((l_mapping[l_index].mcsMaskMSB) << 8) | + l_mapping[l_index].mcsMaskLSB)). + set_VPDFREQMASK(uint8_t(l_mapping[l_index].freqMask)). + set_VPDRANKMASK(uint8_t(((l_mapping[l_index].rankMaskMSB) << 8) | + l_mapping[l_index].rankMaskLSB)). + set_TARGET(i_target). + set_VPDTYPE(i_vpd_info.iv_vpd_type), + "Unsupported configuration"); // build the keyword name o_keywordInfo.kwName[0] = l_first; diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C index 70aa4306e..ea214b833 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C @@ -39,6 +39,7 @@ // mss lib #include +#include #include #include #include @@ -47,7 +48,6 @@ #include #include #include -#include using fapi2::TARGET_TYPE_MCA; using fapi2::TARGET_TYPE_MCS; @@ -3495,78 +3495,92 @@ fapi2::ReturnCode eff_config::decode_vpd(const fapi2::Target& i uint8_t l_mr_blob[mss::VPD_KEYWORD_MAX] = {0}; uint8_t l_cke_blob[mss::VPD_KEYWORD_MAX] = {0}; uint8_t l_dq_blob[mss::VPD_KEYWORD_MAX] = {0}; + std::vector l_mt_blobs(PORTS_PER_MCS, nullptr); + fapi2::VPDInfo l_vpd_info(fapi2::MemVpdData::MT); // For sanity. Not sure this will break us, but we're certainly making assumptions below. static_assert(MAX_DIMM_PER_PORT == 2, "Max DIMM per port isn't 2"); - // Get MT data + // We need to set up all VPD info before calling getVPD, the API assumes this + // For MR we need to tell the VPDInfo the frequency (err ... mt/s - why is this mhz?) + FAPI_TRY( mss::freq(find_target(i_target), l_vpd_info.iv_freq_mhz) ); + FAPI_INF("%s. VPD info - dimm data rate: %d MT/s", c_str(i_target), l_vpd_info.iv_freq_mhz); + + // Make sure to create 0 filled blobs for all the possible blobs, not just for the + // chiplets which are configured. This prevents the decoder from accessing nullptrs + // but the code which uses the VPD will only access the information for the chiplets + // which exist - so the 0's are meaningless + for (auto& b : l_mt_blobs) { - fapi2::VPDInfo l_vpd_info(fapi2::MemVpdData::MT); + b = new uint8_t[mss::VPD_KEYWORD_MAX]; + memset(b, 0, mss::VPD_KEYWORD_MAX); + } - // Check the max for giggles. Programming bug so we should assert. - FAPI_TRY( mss::getVPD(i_target, l_vpd_info, nullptr) ); + // For MT we need to fill in the rank information + // But, of course, the rank information can differ per port. However, the vpd interface doesn't + // allow this in a straight-forward way. So, we have to get VPD blobs for MCS which contain + // ports which have the rank configuration in question. This means, basically, we pass a MCS MT + // blob to the decoder for each MCA, regardless of whether the port configurations are the same. + for (const auto& p : find_targets(i_target)) + { + // Find our blob in the vector of blob pointers + uint8_t* l_mt_blob = l_mt_blobs[mss::index(p)]; + uint64_t l_rank_count_dimm[MAX_DIMM_PER_PORT] = {0}; - if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) + // If we don't have any DIMM, don't worry about it. This will just drop the blob full of 0's into our index. + // This will fill the VPD attributes with 0's which is perfectly ok. + for (const auto& d : mss::find_targets(p)) { - FAPI_ERR("VPD MT keyword is too big for our array"); - fapi2::Assert(false); + uint8_t l_num_master_ranks = 0; + FAPI_TRY( mss::eff_num_master_ranks_per_dimm(d, l_num_master_ranks) ); + l_rank_count_dimm[mss::index(d)] = l_num_master_ranks; } - // Make sure to create 0 filled blobs for all the possible blobs, not just for the - // chiplets which are configured. This prevents the decoder from accessing nullptrs - // but the code which uses the VPD will only access the information for the chiplets - // which exist - so the 0's are meaningless - for (auto& b : l_mt_blobs) - { - b = new uint8_t[mss::VPD_KEYWORD_MAX]; - memset(b, 0, mss::VPD_KEYWORD_MAX); - } + // This value will, of course, be 0 if there is no DIMM in the port. + l_vpd_info.iv_rank_count_dimm_0 = l_rank_count_dimm[0]; + l_vpd_info.iv_rank_count_dimm_1 = l_rank_count_dimm[1]; - // For MT we need to fill in the rank information - // But, of course, the rank information can differ per port. However, the vpd interface doesn't - // allow this in a straight-forward way. So, we have to get VPD blobs for MCS which contain - // ports which have the rank configuration in question. This means, basically, we pass a MCS MT - // blob to the decoder for each MCA, regardless of whether the port configurations are the same. - for (const auto& p : find_targets(i_target)) - { - // Find our blob in the vector of blob pointers - uint8_t* l_mt_blob = l_mt_blobs[mss::index(p)]; - uint64_t l_rank_count_dimm[MAX_DIMM_PER_PORT] = {0}; + FAPI_INF("%s. VPD info - rank count for dimm_0: %d, dimm_1: %d", + c_str(i_target), l_vpd_info.iv_rank_count_dimm_0, l_vpd_info.iv_rank_count_dimm_1); - // If we don't have any DIMM, don't worry about it. This will just drop the blob full of 0's into our index. - // This will fill the VPD attributes with 0's which is perfectly ok. - for (const auto& d : mss::find_targets(p)) + // Get the MCS blob for this specific rank combination *only if* we have DIMM. Remember, + // Cronus can give us functional MCA which have no DIMM - and we'd puke getting the VPD. + if ((l_vpd_info.iv_rank_count_dimm_0 != 0) || (l_vpd_info.iv_rank_count_dimm_1 != 0)) + { + // If getVPD returns us an error, then we don't have VPD for the DIMM configuration. + // This is the root of our plug-rules: if you want a configuration of DIMM to be + // supported, it needs to have VPD defined. Likewise, if you don't want a configuration + // of DIMM supported be sure to leave it out of the VPD. Note that we don't return a specific + // plug-rule error as f/w (Dan) suggested this would duplicate errors leading to confusion. + l_vpd_info.iv_vpd_type = fapi2::MemVpdData::MT; + + // Check the max for giggles. Programming bug so we should assert. + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, nullptr), + "Failed to retrieve MT size from VPD"); + + if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) { - uint8_t l_num_master_ranks = 0; - FAPI_TRY( mss::eff_num_master_ranks_per_dimm(d, l_num_master_ranks) ); - l_rank_count_dimm[mss::index(d)] = l_num_master_ranks; + FAPI_ERR("VPD MT keyword is too big for our array"); + fapi2::Assert(false); } - // This value will, of course, be 0 if there is no DIMM in the port. - l_vpd_info.iv_rank_count_dimm_0 = l_rank_count_dimm[0]; - l_vpd_info.iv_rank_count_dimm_1 = l_rank_count_dimm[1]; - - // Get the MCS blob for this specific rank combination *only if* we have DIMM. Remember, - // Cronus can give us functional MCA which have no DIMM - and we'd puke getting the VPD. - if ((l_vpd_info.iv_rank_count_dimm_0 != 0) || (l_vpd_info.iv_rank_count_dimm_1 != 0)) - { - // If getVPD returns us an error, then we don't have VPD for the DIMM configuration. - // This is the root of our plug-rules: if you want a configuration of DIMM to be - // supported, it needs to have VPD defined. Likewise, if you don't want a configuration - // of DIMM supported be sure to leave it out of the VPD. Note that we don't return a specific - // plug-rule error as f/w (Dan) suggested this would duplicate errors leading to confusion. - FAPI_TRY( mss::getVPD(i_target, l_vpd_info, &(l_mt_blob[0])) ); - } + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, &(l_mt_blob[0])), + "Failed to retrieve MT VPD"); } - } + }// mca - // Get MR data + // Only get the MR blob if we have a freq. It's possible for Cronus to give us an MCS which + // is connected to a controller which has 0 DIMM installed. In this case, we won't have + // a frequency, and thus we'd fail getting the VPD. So we initiaized the VPD to 0's and if + // there's no freq, we us a 0 filled VPD. + if (l_vpd_info.iv_freq_mhz != 0) { - fapi2::VPDInfo l_vpd_info(fapi2::MemVpdData::MR); + l_vpd_info.iv_vpd_type = fapi2::MemVpdData::MR; // Check the max for giggles. Programming bug so we should assert. - FAPI_TRY( mss::getVPD(i_target, l_vpd_info, nullptr) ); + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, nullptr), + "Failed to retrieve MR size from VPD"); if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) { @@ -3574,51 +3588,48 @@ fapi2::ReturnCode eff_config::decode_vpd(const fapi2::Target& i fapi2::Assert(false); } - // For MR we need to tell the VPDInfo the frequency (err ... mt/s - why is this mhz?) - FAPI_TRY( mss::freq(find_target(i_target), l_vpd_info.iv_freq_mhz) ); - - // Only get the MR blob if we have a freq. It's possible for Cronus to give us an MCS which - // is connected to a controller which has 0 DIMM installed. In this case, we won't have - // a frequency, and thus we'd fail getting the VPD. So we initiaized the VPD to 0's and if - // there's no freq, we us a 0 filled VPD. - if (l_vpd_info.iv_freq_mhz != 0) - { - FAPI_TRY( mss::getVPD(i_target, l_vpd_info, &(l_mr_blob[0])) ); - } + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, &(l_mr_blob[0])), + "Failed to retrieve MR VPD"); } - // Get CKE data - { - fapi2::VPDInfo l_vpd_info(fapi2::MemVpdData::CK); + // Until CK/DQ integration is working, we differentiate getting our fake_vpd for those ids. + // This gives us an extended API we can use for testing which won't be seen by HB because we'd use this to limit it +#ifndef __HOSTBOOT_MODULE - // Check the max for giggles. Programming bug so we should assert. - FAPI_TRY( mss::getVPD(i_target, l_vpd_info, nullptr) ); + // Get CKE data + l_vpd_info.iv_vpd_type = fapi2::MemVpdData::CK; - if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) - { - FAPI_ERR("VPD MR keyword is too big for our array"); - fapi2::Assert(false); - } + // Check the max for giggles. Programming bug so we should assert. + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, nullptr), + "Failed to retrieve CK size from VPD"); - FAPI_TRY( mss::getVPD(i_target, l_vpd_info, &(l_cke_blob[0])) ); + if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) + { + FAPI_ERR("VPD CK keyword is too big for our array"); + fapi2::Assert(false); } - // Get DQ data - { - fapi2::VPDInfo l_vpd_info(fapi2::MemVpdData::DQ); + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, &(l_cke_blob[0])), + "Failed to retrieve DQ VPD"); - // Check the max for giggles. Programming bug so we should assert. - FAPI_TRY( mss::getVPD(i_target, l_vpd_info, nullptr) ); + // Get DQ data + l_vpd_info.iv_vpd_type = fapi2::MemVpdData::DQ; - if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) - { - FAPI_ERR("VPD MR keyword is too big for our array"); - fapi2::Assert(false); - } + // Check the max for giggles. Programming bug so we should assert. + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, nullptr), + "Failed to retrieve DQ size from VPD"); - FAPI_TRY( mss::getVPD(i_target, l_vpd_info, &(l_dq_blob[0])) ); + if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) + { + FAPI_ERR("VPD DQ keyword is too big for our array"); + fapi2::Assert(false); } + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, &(l_dq_blob[0])), + "Failed to retrieve DQ VPD"); + +#endif + FAPI_TRY( mss::eff_decode(i_target, l_mt_blobs, l_mr_blob, l_cke_blob, l_dq_blob) ); fapi_try_exit: -- cgit v1.2.1