//****************************************************************************** // targetTest8 //****************************************************************************** uint32_t targetTest8() { uint32_t l_result = 0; uint8_t l_handle = 7; void * l_pHandle = reinterpret_cast<void *>(&l_handle); // Create Target Target l_target(TARGET_TYPE_L4, l_pHandle); // an L4 Target is not a chip if ( l_target.isChip() ) { FAPI_ERR("targetTest8. L4 target incorrectly" " identified itself as a chip"); l_result = 1; } else { if ( !l_target.isChiplet() ) { FAPI_ERR("targetTest8. L4 target failed to identify as a chiplett" ); l_result = 2; } else { FAPI_INF("targetTest8. Success!"); } } // Set the handle pointer to NULL to prevent any problem on destruction l_target.set(NULL); return l_result; }
//------------------------------------------------------------------------------ // function: proc_tod_init // // parameters: i_tod_node Reference to TOD topology (FAPI targets included within) // // returns: FAPI_RC_SUCCESS if TOD topology is successfully initialized // else FAPI or ECMD error is sent through //------------------------------------------------------------------------------ fapi::ReturnCode proc_tod_init(const tod_topology_node* i_tod_node) { fapi::ReturnCode rc; FAPI_INF("proc_tod_init: Start"); do { if (i_tod_node == NULL) { FAPI_ERR("proc_tod_setup: null node passed into function!"); FAPI_SET_HWP_ERROR(rc, RC_PROC_TOD_NULL_NODE); break; } rc = proc_tod_clear_error_reg(i_tod_node); if (!rc.ok()) { FAPI_ERR("proc_tod_setup: Failure clearing TOD error registers!"); break; } //Start configuring each node; (init_tod_node will recurse on each child) rc = init_tod_node(i_tod_node); if (!rc.ok()) { FAPI_ERR("proc_tod_setup: Failure initializing TOD!"); break; } } while (0); FAPI_INF("proc_tod_init: End"); return rc; }
/// /// @brief Equalize the throttles among OCMB chips /// @param[in] i_targets vector of OCMB chips /// @param[in] i_throttle_type thermal boolean to determine whether to calculate throttles based on the power regulator or thermal limits /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note equalizes the throttles to the lowest of runtime and the lowest slot-throttle value /// fapi2::ReturnCode equalize_throttles( const std::vector< fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> >& i_targets, const mss::throttle_type i_throttle_type) { FAPI_INF("Start equalize_throttles for %s type throttling", (( i_throttle_type == mss::throttle_type::THERMAL) ? "THERMAL" : "POWER")); std::vector< fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT> > l_exceeded_power; // Set all of the throttles to the lowest value per port for performance reasons FAPI_TRY(mss::power_thermal::equalize_throttles(i_targets, i_throttle_type, l_exceeded_power)); // Report any port that exceeded the max power limit, and return a failing RC if we have any for (const auto& l_port : l_exceeded_power) { FAPI_ERR(" MEM_PORT %s estimated power exceeded the maximum allowed", mss::c_str(l_port) ); fapi2::current_err = fapi2::FAPI2_RC_FALSE; } FAPI_INF("End equalize_throttles"); return fapi2::current_err; fapi_try_exit: FAPI_ERR("Error calculating equalize_throttles using %s throttling", ((i_throttle_type == mss::throttle_type::POWER) ? "power" : "thermal")); return fapi2::current_err; }
//****************************************************************************** // targetTest1 //****************************************************************************** uint32_t targetTest1() { uint32_t l_result = 0; // Create Target using default constructor Target l_target; // Ensure that the handle pointer is NULL void * l_pHandle = l_target.get(); if (l_pHandle != NULL) { FAPI_ERR("targetTest1. Handle is not NULL"); l_result = 1; } else { // Ensure that the type is TARGET_TYPE_NONE TargetType l_type = l_target.getType(); if (l_type != TARGET_TYPE_NONE) { FAPI_ERR("targetTest1. Type is 0x%x, expected NONE", l_type); l_result = 2; } else { FAPI_INF("targetTest1. Success!"); } } return l_result; }
//------------------------------------------------------------------------------ // function: proc_tod_save_single_reg // // parameters: i_target FAPI target // i_addr SCOM address to read // o_data Buffer to save register read // // returns: FAPI_RC_SUCCESS if the given register was read and saved into buffer // else FAPI or ECMD error is sent through //------------------------------------------------------------------------------ fapi::ReturnCode proc_tod_save_single_reg(const fapi::Target& i_target, const uint64_t i_addr, ecmdDataBufferBase& o_data) { fapi::ReturnCode rc; uint32_t rc_ecmd = 0; FAPI_DBG("proc_tod_save_single_reg: Start"); do { rc_ecmd |= o_data.setBitLength(64); if (rc_ecmd) { FAPI_ERR("proc_tod_save_single_reg: Error 0x%08X in ecmdDataBuffer setup for 0x%016llX SCOM.", rc_ecmd, i_addr); rc.setEcmdError(rc_ecmd); break; } rc=fapiGetScom(i_target,i_addr,o_data); if (!rc.ok()) { FAPI_ERR("proc_tod_save_single_reg: Error from fapiGetScom when retrieving 0x%016llX...", i_addr); break; } FAPI_DBG("proc_tod_save_single_reg: %016llX = %016llX",i_addr, o_data.getDoubleWord(0)); } while(0); FAPI_DBG("proc_tod_save_single_reg: End"); return rc; }
/** * @brief Returns a chip's name and EC level * * @param[in] i_attr Attribute ID (just used for tracing) * @param[in] i_chip Reference to Chip fapi target * @param[out] o_name Filled in with the chip name * @param[out] o_ec Filled in with the chip EC level * * @return fapi::ReturnCode Indicating success or error */ fapi::ReturnCode pllInfoGetChipNameEc( const fapi::getPllRingInfo::Attr i_attr, const fapi::Target & i_chip, fapi::ATTR_NAME_Type & o_name, fapi::ATTR_EC_Type & o_ec) { fapi::ReturnCode l_rc; // As an Attribute Accessor HWP that needs the chip's name/EC to figure out // the data to return, it is valid to access these privileged attributes l_rc = FAPI_ATTR_GET_PRIVILEGED(ATTR_NAME, &i_chip, o_name); if (l_rc) { FAPI_ERR("getPllRingInfoAttr: error getting ATTR_NAME for attr %d", i_attr); } else { l_rc = FAPI_ATTR_GET_PRIVILEGED(ATTR_EC, &i_chip, o_ec); if (l_rc) { FAPI_ERR("getPllRingInfoAttr: error getting ATTR_EC for attr %d", i_attr); } } return l_rc; }
/// /// @brief Check if a given DIMM is functional /// @param[in] i_valid_dimm_bitmap from ATTR_CEN_MSS_EFF_DIMM_FUNCTIONAL_VECTOR /// @param[in] i_port port index [0:1] /// @param[in] i_dimm dimm index [0:1] /// @return true if dimm is functional, false otherwise /// bool is_dimm_functional(const uint8_t i_valid_dimm_bitmap, const uint8_t i_port, const uint8_t i_dimm) { // TODO - RTC:174931 See if we can clean up is_dimm_functional when indexing API is implemented constexpr uint8_t PORT0_DIMM0_BIT_POS = 0; constexpr uint8_t PORT0_DIMM1_BIT_POS = 1; constexpr uint8_t PORT1_DIMM0_BIT_POS = 4; constexpr uint8_t PORT1_DIMM1_BIT_POS = 5; // Map that represents a valid dimm position for ATTR_CEN_MSS_EFF_DIMM_FUNCTIONAL_VECTOR // Taken from attribute description static constexpr uint8_t const VALID_DIMM_POS[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = { { PORT0_DIMM0_BIT_POS, PORT0_DIMM1_BIT_POS }, { PORT1_DIMM0_BIT_POS, PORT1_DIMM1_BIT_POS }, }; if (i_port >= MAX_PORTS_PER_MBA) { FAPI_ERR("Port index out of bounds: %d", i_port); fapi2::Assert(false); } if (i_dimm >= MAX_DIMM_PER_PORT) { FAPI_ERR("DIMM index out of bounds: %d", i_dimm); fapi2::Assert(false); } // We are just checking bits are set from bitmap // that states whether a certain dimm is functional return fapi2::buffer<uint8_t>(i_valid_dimm_bitmap).getBit(VALID_DIMM_POS[i_port][i_dimm]); }
//------------------------------------------------------------------------------ // function: utility subroutine which writes AND/OR mask register to // set/clear desired bits // parameters: i_target => target // i_active_mask => bit mask defining active bits to act on // i_set_not_clear => define desired operation // (true=set, false=clear) // i_and_mask_addr => SCOM address for AND mask register // i_or_mask_addr => SCOM address for OR mask register // returns: FAPI_RC_SUCCESS if operation was successful, else error //------------------------------------------------------------------------------ fapi::ReturnCode proc_fab_iovalid_write_active_mask( const fapi::Target& i_target, ecmdDataBufferBase& i_active_mask, bool i_set_not_clear, const uint32_t& i_and_mask_addr, const uint32_t& i_or_mask_addr) { // data buffer to hold final bit mask ecmdDataBufferBase mask(64); // return codes uint32_t rc_ecmd = 0; fapi::ReturnCode rc; // mark function entry FAPI_DBG("proc_fab_iovalid_write_active_mask: Start"); do { // copy input mask rc_ecmd = i_active_mask.copy(mask); // form final mask based on desired operation (set/clear) if (!i_set_not_clear) { FAPI_DBG("proc_fab_iovalid_write_active_mask: Inverting active mask"); rc_ecmd |= mask.invert(); } // check return code from buffer manipulation operations if (rc_ecmd) { FAPI_ERR("proc_fab_iovalid_write_active_mask: Error 0x%x setting up active mask data buffer", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } // write register (use OR mask address for set operation, // AND mask address for clear operation) rc = fapiPutScom(i_target, i_set_not_clear?i_or_mask_addr:i_and_mask_addr, mask); if (!rc.ok()) { FAPI_ERR("proc_fab_iovalid_write_active_mask: fapiPutScom error (0x%08X)", i_set_not_clear?i_or_mask_addr:i_and_mask_addr); break; } } while (0); // mark function exit FAPI_DBG("proc_fab_iovalid_write_active_mask: End"); return rc; }
//------------------------------------------------------------------------------ // function: proc_tod_clear_error_reg // // parameters: i_tod_node Reference to TOD topology (FAPI targets included within) // // returns: FAPI_RC_SUCCESS if every TOD node is cleared of errors // else FAPI or ECMD error is sent through //------------------------------------------------------------------------------ fapi::ReturnCode proc_tod_clear_error_reg(const tod_topology_node* i_tod_node) { fapi::ReturnCode rc; ecmdDataBufferBase data(64); uint32_t rc_ecmd = 0; fapi::Target* target = i_tod_node->i_target; FAPI_INF("proc_tod_clear_error_reg: Start"); do { if (i_tod_node == NULL) { FAPI_ERR("proc_tod_clear_error_reg: null node passed into function!"); FAPI_SET_HWP_ERROR(rc, RC_PROC_TOD_NULL_NODE); break; } FAPI_DBG("proc_tod_clear_error_reg: Clear any previous errors from TOD_ERROR_REG_00040030"); rc_ecmd |= data.flushTo1(); if (rc_ecmd) { FAPI_ERR("proc_tod_clear_error_reg: Error 0x%08X in ecmdDataBuffer setup for TOD_ERROR_REG_00040030.", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } rc = fapiPutScom(*target, TOD_ERROR_REG_00040030, data); if (!rc.ok()) { FAPI_ERR("proc_tod_clear_error_reg: Could not write TOD_ERROR_REG_00040030."); break; } for (std::list<tod_topology_node*>::const_iterator child = (i_tod_node->i_children).begin(); child != (i_tod_node->i_children).end(); ++child) { tod_topology_node* tod_node = *child; rc = proc_tod_clear_error_reg(tod_node); if (!rc.ok()) { FAPI_ERR("proc_tod_clear_error_reg: Failure clearing errors from downstream node!"); break; } } if (!rc.ok()) { break; // error in above for loop } } while (0); FAPI_INF("proc_tod_clear_error_reg: End"); return rc; }
// This will be used in future Cumulus code /// @brief Platform-level implementation called by putRing() inline ReturnCode platPutRing(const Target<TARGET_TYPE_ALL>& i_target, const scanRingId_t i_address, variable_buffer& i_data, const RingMode i_ringMode) { FAPI_DBG(ENTER_MRK "platPutRing"); ReturnCode l_rc; errlHndl_t l_err = NULL; // Note: Trace is placed here in plat code because PPE doesn't support // trace in common fapi2_hw_access.H bool l_traceit = platIsScanTraceEnabled(); // Extract the component pointer TARGETING::Target* l_target = reinterpret_cast<TARGETING::Target*>(i_target.get()); // Grab the name of the target TARGETING::ATTR_FAPI_NAME_type l_targName = {0}; fapi2::toString(i_target, l_targName, sizeof(l_targName)); // Output buffer must be set to ring's len by user uint64_t l_ringLen = i_data.getBitLength(); uint64_t l_flag = platGetDDScanMode(i_ringMode); size_t l_size = i_data.getLength<uint8_t>(); l_err = deviceWrite(l_target, i_data.pointer(), l_size, DEVICE_SCAN_ADDRESS(i_address, l_ringLen, l_flag)); if (l_err) { FAPI_ERR("platPutRing: deviceRead returns error!"); FAPI_ERR("fapiPutRing failed - Target %s, Addr %.16llX", l_targName, i_address); // Add the error log pointer as data to the ReturnCode l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); } if (l_traceit) { uint64_t l_data = i_data.get<uint64_t>(); FAPI_SCAN("TRACE : PUTRING : %s : %.16llX %.16llX", l_targName, i_address, l_data); } FAPI_DBG(EXIT_MRK "platPutRing"); return l_rc; }
//****************************************************************************** // fapiPutScom function //****************************************************************************** fapi::ReturnCode fapiPutScom(const fapi::Target& i_target, const uint64_t i_address, ecmdDataBufferBase & i_data) { fapi::ReturnCode l_rc; bool l_traceit = platIsScanTraceEnabled(); // call the platform implementation l_rc = platPutScom( i_target, i_address, i_data ); if (l_rc) { FAPI_ERR("fapiPutScom failed - Target %s, Addr %.16llX", i_target.toEcmdString(), i_address); } if( l_traceit ) { FAPI_SCAN( "TRACE : PUTSCOM : %s : %.16llX %.16llX", i_target.toEcmdString(), i_address, i_data.getDoubleWord( 0 ) ); } return l_rc; }
fapi::ReturnCode _fapiGetSpyImage(const fapi::Target& i_target, const char * const i_spyId, ecmdDataBufferBase & o_data, const ecmdDataBufferBase & i_imageData) { fapi::ReturnCode l_rc; bool l_traceit = platIsScanTraceEnabled(); // call the platform implementation l_rc = platGetSpyImage( i_target, i_spyId, o_data, i_imageData ); if (l_rc) { FAPI_ERR("fapiGetSpyImage failed - Target %s, SpyId %s", i_target.toEcmdString(), i_spyId); } if( l_traceit ) { FAPI_SCAN( "TRACE : GETSPYIMAGE : %s : %s %.16llX", i_target.toEcmdString(), i_spyId, o_data.getDoubleWord(0)); } return l_rc; }
fapi::ReturnCode fapiGetRing(const fapi::Target& i_target, const scanRingId_t i_address, ecmdDataBufferBase & o_data, const uint32_t i_ringMode) { fapi::ReturnCode l_rc; bool l_traceit = platIsScanTraceEnabled(); // call the platform implementation l_rc = platGetRing( i_target, i_address, o_data, i_ringMode ); if (l_rc) { FAPI_ERR("fapiGetRing failed - Target %s, Addr 0x%.16llX", i_target.toEcmdString(), i_address); } if( l_traceit ) { FAPI_SCAN( "TRACE : GETRING : %s : %.16llX %.16llX", i_target.toEcmdString(), i_address, o_data.getDoubleWord( 0 ) ); } return l_rc; }
//****************************************************************************** // fapiPutCfamRegister function //****************************************************************************** fapi::ReturnCode fapiPutCfamRegister(const fapi::Target& i_target, const uint32_t i_address, ecmdDataBufferBase & i_data) { fapi::ReturnCode l_rc; bool l_traceit = platIsScanTraceEnabled(); // call the platform implementation l_rc = platPutCfamRegister( i_target, i_address, i_data ); if (l_rc) { FAPI_ERR("platPutCfamRegister failed - Target %s, Addr %.8X", i_target.toEcmdString(), i_address); } if( l_traceit ) { FAPI_SCAN( "TRACE : PUTCFAMREG : %s : %.8X %.8X", i_target.toEcmdString(), i_address, i_data.getWord(0) ); } return l_rc; }
fapi::ReturnCode fapiMultiScom ( const fapi::Target& i_target, fapi::MultiScom& io_multiScomObj) { FAPI_DBG (ENTER_MRK "fapiMultiScom - i_target: %s, # input ops: %d", i_target.toEcmdString (), io_multiScomObj.iv_ScomList.size ()); fapi::ReturnCode l_rc; // Call the platform specific implemetation l_rc = platMultiScom (i_target, io_multiScomObj); if (!l_rc.ok ()) { uint32_t l_retCode = l_rc; FAPI_ERR ("fapiMultiScom Failed with RC: 0x%.8X! i_target: %s, " "# input ops: %d, # ops complete: %d", l_retCode, i_target.toEcmdString (), io_multiScomObj.iv_ScomList.size (), io_multiScomObj.iv_NumOfCompletes); } FAPI_DBG (EXIT_MRK "fapiMultiScom - i_target: %s, # input ops: %d, " "#ops complete: %d", i_target.toEcmdString (), io_multiScomObj.iv_ScomList.size (), io_multiScomObj.iv_NumOfCompletes); return l_rc; }
//------------------------------------------------------------------------------ // function: apply PBCQ/AIB customization via SCOM initfile // parameters: i_target => processor chip target // returns: FAPI_RC_SUCCESS if initfile evaluation is successful, // else error //------------------------------------------------------------------------------ fapi::ReturnCode proc_pcie_config_pbcq( const fapi::Target & i_target) { fapi::ReturnCode rc; std::vector<fapi::Target> targets; // mark function entry FAPI_INF("proc_pcie_config_pbcq: Start"); do { // execute Phase2 SCOM initfile targets.push_back(i_target); FAPI_INF("proc_pcie_config_pbcq: Executing %s on %s", PROC_PCIE_CONFIG_PHASE2_IF, i_target.toEcmdString()); FAPI_EXEC_HWP( rc, fapiHwpExecInitFile, targets, PROC_PCIE_CONFIG_PHASE2_IF); if (!rc.ok()) { FAPI_ERR("proc_pcie_config_pbcq: Error from fapiHwpExecInitfile executing %s on %s", PROC_PCIE_CONFIG_PHASE2_IF, i_target.toEcmdString()); break; } } while(0); // mark function exit FAPI_INF("proc_pcie_config_pbcq: End"); return rc; }
/// /// @brief mrs05_data ctor /// @param[in] a fapi2::TARGET_TYPE_DIMM target /// @param[out] fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok /// mrs05_data::mrs05_data( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc ): iv_ca_parity_latency(fapi2::ENUM_ATTR_EFF_CA_PARITY_LATENCY_DISABLE), iv_crc_error_clear(fapi2::ENUM_ATTR_EFF_CRC_ERROR_CLEAR_CLEAR), iv_ca_parity_error_status(fapi2::ENUM_ATTR_EFF_CA_PARITY_ERROR_STATUS_CLEAR), iv_odt_input_buffer(fapi2::ENUM_ATTR_EFF_ODT_INPUT_BUFF_DEACTIVATED), iv_ca_parity(fapi2::ENUM_ATTR_EFF_CA_PARITY_DISABLE), iv_data_mask(fapi2::ENUM_ATTR_EFF_DATA_MASK_DISABLE), iv_write_dbi(fapi2::ENUM_ATTR_EFF_WRITE_DBI_DISABLE), iv_read_dbi(fapi2::ENUM_ATTR_EFF_READ_DBI_DISABLE) { FAPI_TRY( mss::eff_ca_parity_latency(i_target, iv_ca_parity_latency), "Error in mrs05_data()" ); FAPI_TRY( mss::eff_crc_error_clear(i_target, iv_crc_error_clear), "Error in mrs05_data()" ); FAPI_TRY( mss::eff_ca_parity_error_status(i_target, iv_ca_parity_error_status), "Error in mrs05_data()" ); FAPI_TRY( mss::eff_odt_input_buff(i_target, iv_odt_input_buffer), "Error in mrs05_data()" ); FAPI_TRY( mss::eff_dram_rtt_park(i_target, &(iv_rtt_park[0])), "Error in mrs05_data()" ); FAPI_TRY( mss::eff_ca_parity(i_target, iv_ca_parity), "Error in mrs05_data()" ); FAPI_TRY( mss::eff_data_mask(i_target, iv_data_mask), "Error in mrs05_data()" ); FAPI_TRY( mss::eff_write_dbi(i_target, iv_write_dbi), "Error in mrs05_data()" ); FAPI_TRY( mss::eff_read_dbi(i_target, iv_read_dbi), "Error in mrs05_data()" ); o_rc = fapi2::FAPI2_RC_SUCCESS; return; fapi_try_exit: o_rc = fapi2::current_err; FAPI_ERR("%s unable to get attributes for mrs05", mss::c_str(i_target)); return; }
//****************************************************************************** // fapiUnloadInitFile //****************************************************************************** fapi::ReturnCode fapiUnloadInitFile(const char * i_file, const char *& io_addr, size_t & io_size) { #ifndef __HOSTBOOT_RUNTIME fapi::ReturnCode l_rc = fapi::FAPI_RC_SUCCESS; errlHndl_t l_pError = NULL; FAPI_INF("fapiUnloadInitFile: %s", i_file); l_pError = VFS::module_unload(i_file); if(l_pError) { // Add the error log pointer as data to the ReturnCode FAPI_ERR("fapiUnloadInitFile: module_unload failed %s", i_file); l_rc.setPlatError(reinterpret_cast<void *> (l_pError)); } else { io_addr = NULL; io_size = 0; } #else fapi::ReturnCode l_rc = fapi::FAPI_RC_PLAT_NOT_SUPPORTED_AT_RUNTIME; #endif return l_rc; }
fapi::ReturnCode _fapiPutSpyImage(const fapi::Target& i_target, const spyId_t i_spyId, const ecmdDataBufferBase & i_data, ecmdDataBufferBase & io_imageData) { fapi::ReturnCode l_rc; bool l_traceit = platIsScanTraceEnabled(); // call the platform implementation l_rc = platPutSpyImage( i_target, i_spyId, i_data, io_imageData ); if (l_rc) { FAPI_ERR("fapiPutSpyImage failed - Target %s, SpyId 0x%.16llX", i_target.toEcmdString(), i_spyId); } if( l_traceit ) { FAPI_SCAN( "TRACE : PUTSPYIMG : %s : %.16llX %.16llX", i_target.toEcmdString(), i_spyId, i_data.getDoubleWord(0)); } return l_rc; }
/// @brief Internal function that gets the chip target for cfam access errlHndl_t getCfamChipTarget(const TARGETING::Target* i_target, TARGETING::Target*& o_chipTarget) { errlHndl_t l_err = NULL; // Default to input target o_chipTarget = const_cast<TARGETING::Target*>(i_target); // Check to see if this is a chiplet if (i_target->getAttr<TARGETING::ATTR_CLASS>() == TARGETING::CLASS_UNIT) { // Look for its chip parent TARGETING::PredicateCTM l_chipClass(TARGETING::CLASS_CHIP); TARGETING::TargetHandleList l_list; TARGETING::TargetService& l_targetService = TARGETING::targetService(); (void) l_targetService.getAssociated( l_list, i_target, TARGETING::TargetService::PARENT, TARGETING::TargetService::ALL, &l_chipClass); if ( l_list.size() == 1 ) { o_chipTarget = l_list[0]; } else { // Something is wrong here, can't have more than one parent chip FAPI_ERR("getCfamChipTarget: Invalid number of parent chip for this target chiplet - # parent chips %d", l_list.size()); } } return l_err; }
/// @brief Verify target of a cfam access errlHndl_t verifyCfamAccessTarget(const TARGETING::Target* i_target, const uint32_t i_address) { errlHndl_t l_err = NULL; // Can't access cfam engine on the master processor TARGETING::Target* l_pMasterProcChip = NULL; TARGETING::targetService(). masterProcChipTargetHandle( l_pMasterProcChip ); if( l_pMasterProcChip == i_target ) { FAPI_ERR("verifyCfamAccessTarget: Attempt to access CFAM register %.8X on the master processor chip", i_address); /*@ * @errortype * @moduleid fapi2::MOD_FAPI2_VERIFYCFAMACCESSTARGET * @reasoncode fapi2::RC_INVALID_TARG_TARGET * @userdata1 CFAM Address * @userdata2 HUID of input target * @devdesc verifyCfamAccessTarget> Attempt to access CFAM * on the master processor * @custdesc Internal firmware error */ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, fapi2::MOD_FAPI2_VERIFYCFAMACCESSTARGET, fapi2::RC_INVALID_TARG_TARGET, i_address, TARGETING::get_huid(i_target), true /*SW error*/); l_err->collectTrace(FAPI_TRACE_NAME); } return l_err; }
/** * @brief Returns SPD_MODULE_REVISION_CODE data * * The fields are different sizes for DDR3 and DDR4, this HWP copies the value * to the attribute size in the common FAPI Attribute * * @param[in] i_dimm Reference to DIMM fapi target * @param[in] i_attr The Attribute to get * @param[out] o_pVal Pointer to data buffer filled in with attribute data * @param[in] i_len Size of o_pVal * @param[in] i_type DDR Type * * @return fapi::ReturnCode Indicating success or error */ fapi::ReturnCode get_SPD_MODULE_REVISION_CODE(const fapi::Target & i_dimm, const fapi::getSpdAttr::Attr i_attr, void * o_pVal, const size_t i_len, const fapi::ATTR_SPD_DRAM_DEVICE_TYPE_Type i_type) { fapi::ATTR_SPD_MODULE_REVISION_CODE_Type & o_val = *(reinterpret_cast<fapi::ATTR_SPD_MODULE_REVISION_CODE_Type *>(o_pVal)); o_val = 0; fapi::ReturnCode l_rc = checkSize(i_attr, i_len, sizeof(o_val)); if (!l_rc) { if (i_type == fapi::ENUM_ATTR_SPD_DRAM_DEVICE_TYPE_DDR3) { // Size of DDR3 data matches DDR neutral attribute (uint32_t) l_rc = FAPI_ATTR_GET(ATTR_SPD_MODULE_REVISION_CODE_DDR3, &i_dimm, o_val); if (l_rc) { FAPI_ERR("get_SPD_MODULE_REVISION_CODE: Error getting DDR3 attr"); } } else { // Size of DDR4 data (uint8_t) is smaller than the DDR neutral // attribute (uint32_t) fapi::ATTR_SPD_MODULE_REVISION_CODE_DDR4_Type l_code = 0; l_rc = FAPI_ATTR_GET(ATTR_SPD_MODULE_REVISION_CODE_DDR4, &i_dimm, l_code); if (l_rc) { FAPI_ERR("get_SPD_MODULE_NOMINAL_VOLTAGE: Error getting DDR4 attr"); } else { o_val = static_cast<fapi::ATTR_SPD_MODULE_REVISION_CODE_Type>( l_code); } } } return l_rc; }
// dlopens a shared library and returns the handle int openSharedLib(const std::string & i_libName, void * & o_pLibHandle) { uint32_t rc = fapi2::FAPI2_RC_SUCCESS; std::string sharedLibPath; #ifdef __linux__ #ifdef _LP64 #ifdef __powerpc__ #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ std::string tmp = (i_libName + "_ppc64le.so"); #else std::string tmp = (i_libName + "_ppc64.so"); #endif #else std::string tmp = (i_libName + "_x86_64.so"); #endif // end _LP64 #else std::string tmp = (i_libName + "_x86.so"); #endif //end __linux__ #else #ifdef _LP64 std::string tmp = (i_libName + "_aix64.so"); #else std::string tmp = (i_libName + "_aix.so"); #endif #endif #if defined(ECMD_STATIC_FUNCTIONS) rc = dllFapi2QueryFileLocation(fapi2::FAPI_FILE_HWP, tmp, sharedLibPath, "default"); #else rc = fapi2QueryFileLocation(fapi2::FAPI_FILE_HWP, tmp, sharedLibPath, "default"); #endif if (rc) { FAPI_ERR("fapi2QueryFileLocation failed with rc = 0x%x\n", rc); return rc; } o_pLibHandle = dlopen(sharedLibPath.c_str(), RTLD_LAZY); if (o_pLibHandle == NULL) { FAPI_ERR("dlopen error '%s'\n", dlerror()); return ECMD_FAILURE; } return rc; }
//------------------------------------------------------------------------------ // Subroutine definitions //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // subroutine: // Get the SBE location from SBE VITAL // // parameters: i_target => slave chip target // o_halt_code => halt code (only valid if SBE stopped) // o_istep_num => current istep number (0xMmm) // o_substep_num => current substep within istep // // returns: FAPI_RC_SUCCESS if o_istep_num and o_substep_num are valid, // else error //------------------------------------------------------------------------------ fapi::ReturnCode proc_check_slave_sbe_seeprom_complete_get_location( const fapi::Target & i_target, uint8_t & o_halt_code, uint16_t & o_istep_num, uint8_t & o_substep_num ) { // data buffer to hold register values ecmdDataBufferBase data(64); // return codes uint32_t rc_ecmd = 0; fapi::ReturnCode rc; do { //Check SBE VITAL FAPI_DBG("Checking SBE VITAL reg"); rc = fapiGetScom(i_target, MBOX_SBEVITAL_0x0005001C, data); if(rc) { FAPI_ERR("Error reading SBE VITAL reg\n"); break; } o_halt_code = 0; o_istep_num = 0; o_substep_num = 0; rc_ecmd |= data.extractToRight(&o_halt_code, HALT_CODE_BIT_POSITION, HALT_CODE_BIT_LENGTH); rc_ecmd |= data.extractToRight(&o_istep_num, ISTEP_NUM_BIT_POSITION, ISTEP_NUM_BIT_LENGTH); rc_ecmd |= data.extractToRight(&o_substep_num, SUBSTEP_NUM_BIT_POSITION, SUBSTEP_NUM_BIT_LENGTH); if(rc_ecmd) { FAPI_ERR("Error (0x%x) extracting data from ecmdDataBufferBase", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } } while(0); return rc; }
/// /// @brief Calcuate the throttle values based on throttle type /// @param[in] i_target /// @param[in] i_throttle_type thermal boolean to determine whether to calculate throttles based on the power regulator or thermal limits /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Called in p9_mss_bulk_pwr_throttles /// @note determines the throttle levels based off of the port's power curve, /// sets the slot throttles to the same /// @note Enums are POWER for power egulator throttles and THERMAL for thermal throttles /// @note equalizes the throttles to the lowest of runtime and the lowest slot-throttle value /// fapi2::ReturnCode pwr_throttles( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target, const mss::throttle_type i_throttle_type) { FAPI_INF("Start exp_bulk_pwr_throttle for %s type throttling for %s", (( i_throttle_type == mss::throttle_type::THERMAL) ? "THERMAL" : "POWER"), mss::c_str(i_target)); if (mss::count_dimm (i_target) == 0) { return fapi2::FAPI2_RC_SUCCESS; } uint16_t l_slot = 0; uint16_t l_port = 0; uint32_t l_power = 0; for (const auto& l_port_target : mss::find_targets<fapi2::TARGET_TYPE_MEM_PORT>(i_target)) { fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; //Don't run if there are no dimms on the port if (mss::count_dimm(l_port_target) == 0) { continue; } mss::power_thermal::throttle<> l_pwr_struct(l_port_target, l_rc); FAPI_TRY(l_rc, "Error constructing mss:power_thermal::throttle object for target %s", mss::c_str(l_port_target)); //Let's do the actual work now if ( i_throttle_type == mss::throttle_type::THERMAL) { FAPI_TRY (l_pwr_struct.thermal_throttles()); } else { FAPI_TRY (l_pwr_struct.power_regulator_throttles()); } l_slot = l_pwr_struct.iv_n_slot; l_port = l_pwr_struct.iv_n_port; l_power = l_pwr_struct.iv_calc_port_maxpower; FAPI_INF("For target %s Calculated power is %d, throttle per slot is %d, throttle per port is %d", mss::c_str(l_port_target), l_power, l_slot, l_port); FAPI_TRY(mss::attr::set_port_maxpower( l_port_target, l_power)); FAPI_TRY(mss::attr::set_mem_throttled_n_commands_per_slot( l_port_target, l_slot)); FAPI_TRY(mss::attr::set_mem_throttled_n_commands_per_port( l_port_target, l_port)); } FAPI_INF("End bulk_pwr_throttles for %s", mss::c_str(i_target)); return fapi2::current_err; fapi_try_exit: FAPI_ERR("Error calculating bulk_pwr_throttles using %s throttling", ((i_throttle_type == mss::throttle_type::POWER) ? "power" : "thermal")); return fapi2::current_err; }
//****************************************************************************** // _setHwpError function //****************************************************************************** void ReturnCode::_setHwpError(const HwpReturnCode i_rcValue) { FAPI_ERR("_setHwpError: Creating HWP error 0x%x", i_rcValue); iv_rcValue = i_rcValue; // Forget about any associated data (this is a new error) forgetData(); }
//****************************************************************************** // Constructor //****************************************************************************** ReturnCode::ReturnCode(const ReturnCodes i_rcValue) : iv_rcValue(i_rcValue), iv_pDataRef(NULL) { if (i_rcValue != FAPI_RC_SUCCESS) { FAPI_ERR("ctor: Creating error 0x%x", i_rcValue); } }
// dlcloses a shared library void closeSharedLib(void * i_pLibHandle) { int l_res = dlclose(i_pLibHandle); if (l_res) { FAPI_ERR("dlclose error '%s'\n", dlerror()); } }
// HWP entry point, comments in header fapi::ReturnCode proc_reset_i2cm_bus_fence(const fapi::Target & i_target) { fapi::ReturnCode rc; uint32_t rc_ecmd = 0; ecmdDataBufferBase cfam_data(32); // mark HWP entry FAPI_INF("proc_reset_i2cm_bus_fence: Start"); do { // read FSI GP4 rc = fapiGetCfamRegister(i_target, CFAM_FSI_GP4_0x00002813, cfam_data); if (!rc.ok()) { FAPI_ERR("proc_reset_i2cm_bus_fence: Error from fapiGetCfamRegister (CFAM_FSI_GP4_0x00002813)"); break; } // clear fence bit rc_ecmd |= cfam_data.clearBit(CFAM_FSI_GP4_I2CM_BUS_FENCE_BIT); if (rc_ecmd) { FAPI_ERR("proc_reset_i2cm_bus_fence: Error 0x%x forming FSI GP4 register write data buffer", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } // write back modified data rc = fapiPutCfamRegister(i_target, CFAM_FSI_GP4_0x00002813, cfam_data); if (!rc.ok()) { FAPI_ERR("proc_reset_i2cm_bus_fence: Error from fapiGetCfamRegister (CFAM_FSI_GP4_0x00002813)"); break; } } while(0); // mark HWP exit FAPI_INF("proc_reset_i2cm_bus_fence: End"); return rc; }
/// @brief passing a 'Put Ring from Image' message to SBE with RingId_t ReturnCode platPutRing(const Target<TARGET_TYPE_ALL>& i_target, const RingId_t i_ringID, const RingMode i_ringMode = RING_MODE_HEADER_CHECK) { FAPI_DBG("Entering: platPutRing() with RingId_t"); ReturnCode l_rc = FAPI2_RC_SUCCESS; errlHndl_t l_err = NULL; // Note: Trace is placed here in plat code because PPE doesn't support // trace in common fapi2_hw_access.H bool l_traceit = platIsScanTraceEnabled(); //convert const RingId_t to RingId_t RingId_t l_ringID = reinterpret_cast<RingId_t>(i_ringID); // Extract the component pointer TARGETING::Target* l_target = reinterpret_cast<TARGETING::Target*>(i_target.get()); // Grab the name of the target TARGETING::ATTR_FAPI_NAME_type l_targName = {0}; fapi2::toString(i_target, l_targName, sizeof(l_targName)); uint64_t l_flag = platGetDDScanMode(i_ringMode); size_t l_size = (size_t) 0; FAPI_DBG("platPutRing l_target : %.16llX i_targetType %.16llX", l_target, l_target->getAttr<TARGETING::ATTR_TYPE>()); FAPI_DBG("platPutRing l_RingID :" " %.16llX i_ringMode %.16llX l_flag %.16llX", static_cast<uint64_t>(l_ringID), i_ringMode, l_flag ); l_err = deviceWrite(l_target, nullptr, l_size, DEVICE_SCAN_SBE_ADDRESS(l_ringID,i_ringMode,l_flag)); if(l_err) { FAPI_ERR("platPutRing: deviceWrite returns error!"); // Add the error log pointer as data to the ReturnCode l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_err)); } if (l_traceit) { FAPI_SCAN("TRACE : PUTRING w RingId_t : %s : %.16llX", l_targName, static_cast<uint64_t>(l_ringID)); } FAPI_DBG(EXIT_MRK "platPutRing() with RingId_t"); return l_rc; }