From 77b63192f398181a009630bcdbec28c5918b7c5c Mon Sep 17 00:00:00 2001 From: Thi Tran Date: Mon, 18 Sep 2017 14:19:02 -0500 Subject: [PATCH] Share common code between p9_l2_flush and p9_l2err_linedelete Change-Id: I547078b1e0fc7adec767402faf5e64e4b4390bc9 RTC: 178071 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/46359 Tested-by: FSP CI Jenkins Tested-by: Jenkins Server Tested-by: HWSV CI Tested-by: PPE CI Tested-by: Hostboot CI Reviewed-by: Joseph J. McGill Reviewed-by: Benjamin Gass Reviewed-by: Jennifer A. Stofer Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/46385 Reviewed-by: Hostboot Team Reviewed-by: Sachin Gupta --- .../p9/procedures/hwp/nest/p9_l2_flush.C | 227 +++++++++--------- .../p9/procedures/hwp/nest/p9_l2_flush.H | 49 +++- .../xml/error_info/p9_l2_flush_errors.xml | 16 +- 3 files changed, 161 insertions(+), 131 deletions(-) diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_l2_flush.C b/src/import/chips/p9/procedures/hwp/nest/p9_l2_flush.C index dc4358955..ec447cdb0 100755 --- a/src/import/chips/p9/procedures/hwp/nest/p9_l2_flush.C +++ b/src/import/chips/p9/procedures/hwp/nest/p9_l2_flush.C @@ -24,7 +24,7 @@ /* IBM_PROLOG_END_TAG */ /// -/// @file p9_l2_flush.H +/// @file p9_l2_flush.C /// @brief Flush the P9 L2 cache (FAPI) /// /// *HWP HWP Owner : Benjamin Gass @@ -57,138 +57,133 @@ enum // Function definitions //------------------------------------------------------------------------------ -///----------------------------------------------------------------------------- -/// @brief Utility subroutine to initiate L2 cache flush via purge engine. -/// -/// @param[in] i_target EX target -/// @param[in] i_regAddr The scom address to use -/// @param[in] i_purgeData Structure having values for MEM, CGC, BANK -/// passed by the user -/// -/// @return FAPI2_RC_SUCCESS if purge operation was started, -/// RC_P9_L2_FLUSH_PURGE_REQ_OUTSTANDING if a prior purge -/// operation has not yet completed -/// else FAPI getscom/putscom return code for failing operation -///----------------------------------------------------------------------------- -fapi2::ReturnCode l2_flush_start( +/// See doxygen in header file +fapi2::ReturnCode purgeCompleteCheck( const fapi2::Target& i_target, - const uint32_t i_regAddr, - const p9core::purgeData_t& i_purgeData) + const uint64_t i_busyCount, + fapi2::buffer& o_prdPurgeCmdReg) { - fapi2::buffer l_cmdReg; - fapi2::buffer l_purgeCmd; + FAPI_DBG("Entering purgeCompleteCheck"); + uint64_t l_loopCount = 0; - FAPI_DBG("l2_flush_start: Enter"); + do + { + FAPI_TRY(fapi2::getScom(i_target, EX_PRD_PURGE_CMD_REG, o_prdPurgeCmdReg), + "Error from getScom EX_PRD_PURGE_CMD_REG"); - // ensure that purge engine is idle before starting flush - // poll Purge Engine status - FAPI_DBG("Reading L2 Purge Engine Command Register to check status"); - FAPI_TRY(fapi2::getScom(i_target, i_regAddr, l_cmdReg)); - - // check to see if this reg is idle and ready to accept a new command - FAPI_ASSERT(!l_cmdReg.getBit(), - fapi2::P9_L2_FLUSH_PURGE_REQ_OUTSTANDING() - .set_TARGET(i_target) - .set_CMD_REG(l_cmdReg) - .set_CMD_REG_ADDR(i_regAddr), - "Previous purge request has not completed for target"); - - // write PURGE_CMD_TRIGGER bit in Purge Engine Command Register - // ensure PURGE_CMD_TYPE/MEM/CGC/BANK are clear to specify flush - // of entire cache - FAPI_DBG("Write L2 Purge Engine Command Register to initiate cache flush"); - l_purgeCmd.insert(i_purgeData.iv_cmdType); + // Check state of PURGE_CMD_ERR + FAPI_ASSERT(!o_prdPurgeCmdReg.getBit(), + fapi2::P9_PURGE_CMD_REG_ERR() + .set_TARGET(i_target) + .set_CMD_REG(o_prdPurgeCmdReg), + "Purge failed. EX_PRD_PURGE_CMD_REG_ERR set"); - l_purgeCmd.insert(i_purgeData.iv_cmdMem); + // Check the EX_PRD_PURGE_CMD_REG_BUSY bit from scom register + if ( !o_prdPurgeCmdReg.getBit(EX_PRD_PURGE_CMD_REG_BUSY) ) + { + // PURGE is done, get out + break; + } + else + { + l_loopCount++; + + if (l_loopCount > i_busyCount) + { + // Time out, exit loop + break; + } + + // Delay 10ns for each loop + FAPI_TRY(fapi2::delay(P9_L2_FLUSH_HW_NS_DELAY, + P9_L2_FLUSH_SIM_CYCLE_DELAY), + "Fapi Delay call failed."); + } + } + while (1); - l_purgeCmd.insert(i_purgeData.iv_cmdBank); + // Error out if still busy + if (l_loopCount > i_busyCount) + { + // engine busy, dump status + FAPI_DBG("Purge engine busy (reg_busy = %d, busy_on_this = %d," + " sm_busy = %d)", + o_prdPurgeCmdReg.getBit(), + o_prdPurgeCmdReg.getBit(), + o_prdPurgeCmdReg.getBit()); - l_purgeCmd.insert(i_purgeData.iv_cmdCGC); + FAPI_ASSERT(false, fapi2::P9_PURGE_COMPLETE_TIMEOUT() + .set_TARGET(i_target) + .set_COUNT_THRESHOLD(i_busyCount) + .set_CMD_REG(o_prdPurgeCmdReg), + "Previous purge request has not completed for target"); + } - l_purgeCmd.setBit(); +fapi_try_exit: + FAPI_DBG("Exiting purgeCompleteCheck - Counter: %d; prdPurgeCmdReg: 0x%.16llX", + l_loopCount, o_prdPurgeCmdReg); + return fapi2::current_err; +} + +/// See doxygen in header file +fapi2::ReturnCode setupAndTriggerPrdPurge( + const fapi2::Target& i_target, + const p9core::purgeData_t& i_purgeData, + fapi2::buffer& i_prdPurgeCmdReg) +{ + FAPI_DBG("setupAndTriggerPrdPurge: Enter"); - FAPI_TRY(fapi2::putScom(i_target, i_regAddr, l_purgeCmd)); + // Start with current CMD reg value + fapi2::buffer l_cmdReg = i_prdPurgeCmdReg; + + // Write PURGE_CMD_TRIGGER bit in Purge Engine Command Register + // ensure PURGE_CMD_TYPE/MEM/CGC/BANK are clear to specify flush + // of entire cache + FAPI_DBG("Write L2 Purge Engine Command Register to initiate cache flush"); + l_cmdReg.insert(i_purgeData.iv_cmdType); + l_cmdReg.insert(i_purgeData.iv_cmdMem); + l_cmdReg.insert(i_purgeData.iv_cmdBank); + l_cmdReg.insert(i_purgeData.iv_cmdCGC); + l_cmdReg.setBit(); + + FAPI_TRY(fapi2::putScom(i_target, EX_PRD_PURGE_CMD_REG, l_cmdReg), + "Error from putScom EX_PRD_PURGE_CMD_REG"); fapi_try_exit: - FAPI_DBG("l2_flush_start: Exit"); + FAPI_DBG("setupAndTriggerPrdPurge: Exit"); return fapi2::current_err; } ///----------------------------------------------------------------------------- -/// @brief Utility subroutine to poll L2 purge engine status, looking for -/// clean idle state. +/// @brief Utility subroutine to initiate L2 cache flush via purge engine. /// -/// @param[in] i_target EX chiplet target -/// @param[in] i_regAddr Purge engine register SCOM address +/// @param[in] i_target EX target +/// @param[in] i_purgeData Structure having values for MEM, CGC, BANK +/// passed by the user /// -/// @return FAPI2_RC_SUCCESS if engine status returns as idle (with no errors) -/// before maximum number of polls has been reached -/// RC_P9_L2_FLUSH_CMD_ERROR -/// if purge command error reported, -/// RC_P9_L2_FLUSH_CMD_TIMEOUT -/// if purge operation did not complete prior to polling limit, -/// else FAPI getscom/putscom return code for failing operation +/// @return FAPI2_RC_SUCCESS if purge operation was started, +/// else error code. ///----------------------------------------------------------------------------- -fapi2::ReturnCode l2_flush_check_status( +fapi2::ReturnCode l2_flush_start( const fapi2::Target& i_target, - const uint32_t i_regAddr) + const p9core::purgeData_t& i_purgeData) { + FAPI_DBG("l2_flush_start: Enter"); fapi2::buffer l_cmdReg; - uint32_t l_polls = 1; - - FAPI_DBG("l2_flush_check_status: Enter"); - - while(1) - { - // poll Purge Engine status - FAPI_DBG("Reading L2 Purge Engine Command Register to check status"); - FAPI_TRY(fapi2::getScom(i_target, i_regAddr, l_cmdReg)); - - // check state of PURGE_CMD_ERR - FAPI_ASSERT(!l_cmdReg.getBit(), - fapi2::P9_L2_FLUSH_CMD_ERROR() - .set_TARGET(i_target) - .set_CMD_REG(l_cmdReg) - .set_CMD_REG_ADDR(i_regAddr), - "Purge failed. EX_PRD_PURGE_CMD_REG_ERR set"); - // check to see if this reg is idle and ready to accept a new command - if (!l_cmdReg.getBit()) - { - FAPI_DBG("Purge engine idle"); - break; - } - - // engine busy, dump status - FAPI_DBG("Purge engine busy (reg_busy = %d, busy_on_this = %d," - " sm_busy = %d)", - l_cmdReg.getBit(), - l_cmdReg.getBit(), - l_cmdReg.getBit()); - - // check if loop count has expired - FAPI_ASSERT((l_polls < P9_L2_FLUSH_MAX_POLLS), - fapi2::P9_L2_FLUSH_CMD_TIMEOUT() - .set_TARGET(i_target) - .set_CMD_REG(l_cmdReg) - .set_CMD_REG_ADDR(i_regAddr) - .set_NUMBER_OF_ATTEMPTS(l_polls), - "Purge engine still busy after %d loops", l_polls); - - // l_polls left, delay prior to next poll - FAPI_DBG("%d loops done, delaying before next poll", l_polls); + // Ensure that purge engine is idle before starting flush + // poll Purge Engine status + FAPI_TRY(purgeCompleteCheck(i_target, 0, l_cmdReg), // 0 = no wait + "Error returned from purgeCompleteCheck call"); - FAPI_TRY(fapi2::delay(P9_L2_FLUSH_HW_NS_DELAY, - P9_L2_FLUSH_SIM_CYCLE_DELAY)); - - l_polls++; - } + FAPI_TRY(setupAndTriggerPrdPurge(i_target, i_purgeData, l_cmdReg), + "Error returned from setupAndTriggerPrdPurge"); fapi_try_exit: - FAPI_DBG("l2_flush_check_status: Exit"); + FAPI_DBG("l2_flush_start: Exit"); return fapi2::current_err; } @@ -200,22 +195,22 @@ fapi2::ReturnCode p9_l2_flush( const fapi2::Target & i_target, const p9core::purgeData_t& i_purgeData) { + fapi2::buffer l_cmdReg; + FAPI_DBG("Entering p9_l2_flush: i_purgeData [iv_cmdType: 0x%x] " "[iv_cmdMem : 0x%x] [iv_cmdBank: 0x%x] [iv_cmdCGC : 0x%x]", i_purgeData.iv_cmdType, i_purgeData.iv_cmdMem, i_purgeData.iv_cmdBank, i_purgeData.iv_cmdCGC); - uint32_t l_regAddr = EX_PRD_PURGE_CMD_REG; + // Initiate flush + FAPI_TRY(l2_flush_start(i_target, i_purgeData), + "Error returned from l2_flush_start()"); - // initiate flush - FAPI_TRY(l2_flush_start(i_target, l_regAddr, i_purgeData)); - - // check that flush completes and the purge engine is idle - // before exiting - FAPI_TRY(l2_flush_check_status(i_target, l_regAddr)); + // Check for purge complete + FAPI_TRY(purgeCompleteCheck(i_target, P9_L2_FLUSH_MAX_POLLS, l_cmdReg), + "Error returned from purgeCompleteCheck call"); fapi_try_exit: FAPI_DBG("p9_l2_flush: Exit"); return fapi2::current_err; } - diff --git a/src/import/chips/p9/procedures/hwp/nest/p9_l2_flush.H b/src/import/chips/p9/procedures/hwp/nest/p9_l2_flush.H index a54ad6390..af02fccd8 100755 --- a/src/import/chips/p9/procedures/hwp/nest/p9_l2_flush.H +++ b/src/import/chips/p9/procedures/hwp/nest/p9_l2_flush.H @@ -93,22 +93,59 @@ typedef fapi2::ReturnCode (*p9_l2_flush_FP_t) extern "C" { +/// +/// @brief Utility function to check for a purge operation to be completed. +/// This function polls the EX_PRD_PURGE_CMD_REG_BUSY bit of +/// EX_PRD_PURGE_CMD_REG. +/// - If this bit is clear before the input loop threshold is +/// reached, it returns FAPi2_RC_SUCCESS. +/// - Otherwise, it returns an error code. +/// +/// @param[in] i_target => EX chiplet target +/// @param[in] i_busyCount => Max busy count waiting for PURGE to complete. +/// @param[out] o_prdPurgeCmdReg => EX_PRD_PURGE_CMD_REG value. +/// +/// @return FAPI2_RC_SUCCESS if engine status returns as idle (with no errors) +/// before maximum number of polls has been reached +/// else, return error. + fapi2::ReturnCode purgeCompleteCheck( + const fapi2::Target& i_target, + const uint64_t i_busyCount, + fapi2::buffer& o_prdPurgeCmdReg); + +///----------------------------------------------------------------------------- +/// @brief Utility subroutine to setup and trigger a PRD PURGE based +/// on input purge data specification. +/// +/// @param[in] i_target EX target +/// @param[in] i_purgeData Structure having values for MEM, CGC, BANK +/// passed by the user +/// @param[in] i_prdPurgeCmdReg EX_PRD_PURGE_CMD_REG value. +/// +/// @return FAPI2_RC_SUCCESS if purge operation was started, +/// else error code. +///----------------------------------------------------------------------------- + fapi2::ReturnCode setupAndTriggerPrdPurge( + const fapi2::Target& i_target, + const p9core::purgeData_t& i_purgeData, + fapi2::buffer& i_prdPurgeCmdReg); + /// /// @brief Flush entire content of L2 cache via purge engine /// @param[in] i_target EX target /// @param[in] i_purgeData Specifies a particular purge type /// @return: FAPI2_RC_SUCCESS if purge operation completes successfully, -/// RC_P9_L2_FLUSH_PURGE_REQ_OUTSTANDING +/// P9_L2_FLUSH_PURGE_REQ_OUTSTANDING /// if called when existing L2 purge is in progress, -/// RC_P9_L2_FLUSH_CMD_TIMEOUT +/// RC_P9_PURGE_COMPLETE_TIMEOUT /// if purge operation does not complete in expected time, -/// RC_P9_L2_FLUSH_CMD_ERROR +/// RC_P9_PURGE_CMD_REG_ERR /// if purge operation reports error, /// else FAPI getscom/putscom return code for failing operation /// - fapi2::ReturnCode p9_l2_flush(const fapi2::Target < fapi2::TARGET_TYPE_EX > - & i_target, - const p9core::purgeData_t& i_purgeData); + fapi2::ReturnCode p9_l2_flush( + const fapi2::Target < fapi2::TARGET_TYPE_EX >& i_target, + const p9core::purgeData_t& i_purgeData); } // end of extern C diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_l2_flush_errors.xml b/src/import/chips/p9/procedures/xml/error_info/p9_l2_flush_errors.xml index 81d10dd01..62f474c21 100755 --- a/src/import/chips/p9/procedures/xml/error_info/p9_l2_flush_errors.xml +++ b/src/import/chips/p9/procedures/xml/error_info/p9_l2_flush_errors.xml @@ -28,8 +28,8 @@ RC_P9_L2_FLUSH_PURGE_REQ_OUTSTANDING TARGET + COUNT_THRESHOLD CMD_REG - CMD_REG_ADDR A previous L2 purge request has not finished REG_FFDC_PROC_L2_REGISTERS @@ -47,13 +47,12 @@ - RC_P9_L2_FLUSH_CMD_ERROR + RC_P9_PURGE_CMD_REG_ERR TARGET CMD_REG - CMD_REG_ADDR Procedure: p9_l2_flush - L2 flush operation failed, see L2 Purge Engine Command Register for error. + EX_PRD_PURGE_CMD_REG_ERR bit is set in Purge Engine Command Register. REG_FFDC_PROC_L2_REGISTERS @@ -74,15 +73,14 @@ - RC_P9_L2_FLUSH_CMD_TIMEOUT + RC_P9_PURGE_COMPLETE_TIMEOUT TARGET CMD_REG - CMD_REG_ADDR - NUMBER_OF_ATTEMPTS + COUNT_THRESHOLD Procedure: p9_l2_flush - L2 flush operation timed out waiting for purge busy indication to clear in - L2 Purge Engine Command Register. + Timed out waiting for purge busy indication to clear in L2 Purge Engine + Command Register. REG_FFDC_PROC_L2_REGISTERS