/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* $Source: src/usr/hwpf/hwp/bus_training/io_fir_isolation.C $ */ /* */ /* IBM CONFIDENTIAL */ /* */ /* COPYRIGHT International Business Machines Corp. 2013 */ /* */ /* p1 */ /* */ /* Object Code Only (OCO) source materials */ /* Licensed Internal Code Source Materials */ /* IBM HostBoot Licensed Internal Code */ /* */ /* The source code for this program is not published or otherwise */ /* divested of its trade secrets, irrespective of what has been */ /* deposited with the U.S. Copyright Office. */ /* */ /* Origin: 30 */ /* */ /* IBM_PROLOG_END_TAG */ // $Id: io_fir_isolation.C,v 1.9 2013/04/19 10:28:27 jaswamin Exp $ // *!*************************************************************************** // *! (C) Copyright International Business Machines Corp. 2012 , 2013 // *! All Rights Reserved -- Property of IBM // *! *** IBM Confidential *** // *!*************************************************************************** // *! FILENAME : io_fir_isolation.C // *! TITLE : // *! DESCRIPTION : To isolate the error causing the firs to flag // *! CONTEXT : // *! // *! OWNER NAME : Swaminathan, Janani Email: jaswamin@in.ibm.com // *! BACKUP NAME : Varghese, Varkey Email: varkey.kv@in.ibm.com // *! // *!*************************************************************************** // CHANGE HISTORY: //------------------------------------------------------------------------------ // Version:|Author: | Date: | Comment: // --------|--------|--------|-------------------------------------------------- // 1.9 |jaswamin|04/19/13| Fixes for firmware compile issues. // 1.8 |jaswamin|03/22/13| Added comments // 1.7 |jaswamin|03/18/13| Changed indentation // 1.6 |jaswamin|03/13/13| Returncode logging // 1.5 |jaswamin|03/12/13| Return in case of a gcr operation error. // 1.4 |jaswamin|03/06/13| Removed commented out portion. // 1.3 |jaswamin|03/04/13| Changes as per review comment. // 1.2 |jaswamin|02/20/13| Changes as per review comment // 1.1 |jaswamin|02/14/13| Initial check in . //------------------------------------------------------------------------------ #include #include "io_fir_isolation.H" //#include "gcr_funcs.H" //#include "io_clear_firs.H" extern "C" { using namespace fapi; //! Function : io_fir_too_many_bus_err_isolation //! Parameters : i_target => FAPI target, //! chip_interface => io_chip_interface viz., A, X, DMI, CEN //! current_group => current clock group under test in the interface //! Returns : o_rc => FFDC data for too many bus error. This includes the target //! details and the source of the error. //! Description : This function provides the target details including the clock group //! which had this error. This is sent as FFDC data along with the training //! register contents. ReturnCode io_fir_too_many_bus_err_isolation(const fapi::Target &i_target, io_interface_t i_chip_interface, uint32_t i_current_group){ ReturnCode o_rc; ecmdDataBufferBase error_data(16); uint32_t bitPos=0x0080; o_rc=GCR_read(i_target , i_chip_interface, rx_fir_training_pg, i_current_group,0, error_data); if(o_rc) return o_rc; if(error_data.isBitSet(8,1)){ error_data.setAnd(bitPos,0,16); ecmdDataBufferBase & BUS_ERROR_REG = error_data; //bit1 of the register represnts the spare deployed bit. const fapi::Target & CHIP_TARGET= i_target; FAPI_SET_HWP_ERROR(o_rc,IO_FIR_TOO_MANY_BUS_ERROR_RC); } return(o_rc); } //! Function : io_fir_recal_error_isolation //! Parameters : i_target => FAPI target, //! chip_interface => io_chip_interface viz., A, X, DMI, CEN //! current_group => current clock group under test in the interface //! Returns : o_rc => FFDC data for recal error. This includes the target details //! and the source of the error. //! Description : This function collects the register contents of the training register //! that would help root cause the error which could be due to //! dynamic repair fail or dynamic recal fail. This is given //! as FFDC data. ReturnCode io_fir_recal_error_isolation(const fapi::Target &i_target, io_interface_t i_chip_interface, uint32_t i_current_group){ ReturnCode o_rc; ecmdDataBufferBase error_data(16); uint32_t bitPos=0x1200; o_rc=GCR_read(i_target , i_chip_interface, rx_fir_training_pg, i_current_group,0, error_data); if(o_rc) return o_rc; if(error_data.isBitSet(3,1) || error_data.isBitSet(6,1)){ //can be caused by dynamic repair or recal error (bits 3 and 6 respectively) error_data.setAnd(bitPos,0,16); ecmdDataBufferBase & RECAL_ERROR_REG = error_data ; //bit1 of the register represnts the spare deployed bit. const fapi::Target & CHIP_TARGET= i_target; FAPI_SET_HWP_ERROR(o_rc,IO_FIR_RECALIBRATION_ERROR_RC); } return(o_rc); } //! Function : io_fir_max_spares_exceeded_isolation //! Parameters : i_target => FAPI target, //! chip_interface => io_chip_interface viz., A, X, DMI, CEN //! current_group => current clock group under test in the interface //! Returns : o_rc => FFDC data for maximum deployable spares exceeded error. //! This includes the target details and the source of the error. //! Description : This function collects the register contents of the training register //! that would help root cause the error as being from pre/during training, //! post training or during recal that caused the spares to exceed. //! This is provided as FFDC dump. ReturnCode io_fir_max_spares_exceeded_isolation(const fapi::Target &i_target, io_interface_t i_chip_interface, uint32_t i_current_group){ ReturnCode o_rc; ecmdDataBufferBase error_data(16); uint32_t bitPos=0x2680; o_rc=GCR_read(i_target , i_chip_interface, rx_fir_training_pg, i_current_group,0, error_data); if(o_rc) return o_rc; if(error_data.isBitSet(2,1) || error_data.isBitSet(5,1)|| error_data.isBitSet(8,1)){ // can be caused by a static (pre training - bit 2) or dynamic (post training - bit 5) or recal(bit 8) error_data.setAnd(bitPos,0,16); ecmdDataBufferBase & SPARE_ERROR_REG = error_data; //bit2 /bit 5 /bit 8of the register represents the max spare exceeded bit.To determine what caused the max spares exceeded error const fapi::Target & CHIP_TARGET= i_target; FAPI_SET_HWP_ERROR(o_rc,IO_FIR_MAX_SPARES_EXCEEDED_FIR_RC); } return(o_rc); } //! Function : io_fir_spare_deployed_isolation //! Parameters : i_target => FAPI target, //! chip_interface => io_chip_interface viz., A, X, DMI, CEN //! current_group => current clock group under test in the interface //! Returns : o_rc => FFDC data for spare deployed error. This includes the //! target details and the source of the error. //! Description : This function collects the register contents of the training register //! that would help root cause the error as being from pre/during training, //! post training or during recal that caused the spares to be deployed. //! This is provided as FFDC dump. ReturnCode io_fir_spare_deployed_isolation(const fapi::Target &i_target, io_interface_t i_chip_interface, uint32_t i_current_group){ ReturnCode o_rc; ecmdDataBufferBase error_data(16); uint32_t bitPos=0x6900; o_rc=GCR_read(i_target , i_chip_interface, rx_fir_training_pg, i_current_group,0, error_data); if(o_rc) return o_rc; if(error_data.isBitSet(1,1) || error_data.isBitSet(4,1) || error_data.isBitSet(7,1)){ // can be caused by a spare deployment prior to training , post training or during recal error_data.setAnd(bitPos,0,16); ecmdDataBufferBase & SPARE_ERROR_REG = error_data; //bit1 /bit4 / bit 7 of the register represnts the spare deployed bit. To determine which type of error caused the spare to be deployed const fapi::Target & CHIP_TARGET= i_target; FAPI_SET_HWP_ERROR(o_rc,IO_FIR_SPARES_DEPLOYED_FIR_RC); } return(o_rc); } //! Function : io_fir_tx_parity_isolation //! Parameters : i_target => FAPI target, //! chip_interface => io_chip_interface viz., A, X, DMI, CEN //! current_group => current clock group under test in the interface //! Returns : o_rc => FFDC data for the tx fir parity error. This includes //! the target details, the parity error that caused this bit to be set //! and the lane id if it is a lane level error. //! Description : This function collects the register contents that would help //! determine the source of the parity error and provides it as a FFDC data dump. ReturnCode io_fir_tx_parity_isolation(const fapi::Target &i_target, io_interface_t i_chip_interface, uint32_t i_current_group){ ReturnCode o_rc; ecmdDataBufferBase error_data(16); uint32_t loop_val=0; uint32_t lane,group; if(i_chip_interface==CP_FABRIC_X0){ lane=77; } else if(i_chip_interface==CP_FABRIC_A0){ lane=23; } else if(i_chip_interface==CP_IOMC0_P0){ lane=17; } else{ lane=24; } for(loop_val=0;loop_val FAPI target, //! chip_interface => io_chip_interface viz., A, X, DMI, CEN //! current_group => current clock group under test in the interface //! Returns : o_rc => FFDC data for the rx fir parity error. This includes //! the target details, the parity error that caused this bit to be set //! and the lane id if it is a lane level error. //! Description : This function collects the register contents that would help determine //! the source of the parity error and provides it as a FFDC data dump. ReturnCode io_fir_rx_parity_isolation(const fapi::Target &i_target, io_interface_t i_chip_interface, uint32_t i_current_group){ ReturnCode o_rc; ecmdDataBufferBase error_data(16); uint32_t loop_val=0; uint32_t lane,group; //in case its bit 0 it is the rx_parity error. To find which bit is set read the registers that contribute to it. This is a per lane register. Hence we need to loop through each //lane to determine which is erroring out. if(i_chip_interface==CP_FABRIC_X0){ lane=77; } else if(i_chip_interface==CP_FABRIC_A0){ lane=23; } else if(i_chip_interface==CP_IOMC0_P0){ lane=24; } else{ lane=17; } for(loop_val=0;loop_val FAPI target, //! chip_interface => io_chip_interface viz., A, X, DMI, CEN //! current_group => current clock group under test in the interface //! fir_data => data in the 64 bit flat scom fir register //! Returns : o_rc => FFDC data for the FIR error if any (determined using the bit //! set in the 64 bit fir register) //! Description : This function determines the type of error based on the fir bit that //! is set and calls the appropriate isolation function for that error. ReturnCode io_error_isolation(const fapi::Target &i_target, io_interface_t i_chip_interface, uint32_t i_current_group, ecmdDataBufferBase &i_fir_data){ ReturnCode o_rc; ecmdDataBufferBase error_data(16),id_data(16); //need to determine what error it represents. //if it is a rx_parity error if(i_fir_data.isBitSet(RX_PARITY,1)){ if(o_rc) fapiLogError(o_rc); o_rc=io_fir_rx_parity_isolation(i_target,i_chip_interface,i_current_group); } //check for tx_parity error if(i_fir_data.isBitSet(TX_PARITY,1)){ if(o_rc) fapiLogError(o_rc); o_rc=io_fir_tx_parity_isolation(i_target,i_chip_interface,i_current_group); } //GCR hang error if(i_fir_data.isBitSet(GCR_HANG_ERROR,1)){ //check whether the gcr hang error bit is set if(o_rc) fapiLogError(o_rc); const fapi::Target & CHIP_TARGET= i_target; FAPI_SET_HWP_ERROR(o_rc,IO_FIR_GCR_HANG_ERROR_RC); } //spare deploy? if(i_fir_data.isBitSet(BUS0_SPARE_DEPLOYED,1) || i_fir_data.isBitSet(BUS1_SPARE_DEPLOYED,1) || i_fir_data.isBitSet(BUS2_SPARE_DEPLOYED,1) || i_fir_data.isBitSet(BUS3_SPARE_DEPLOYED,1) || i_fir_data.isBitSet(BUS4_SPARE_DEPLOYED,1) ){ if(o_rc) fapiLogError(o_rc); o_rc=io_fir_spare_deployed_isolation(i_target,i_chip_interface,i_current_group); } //maximum spares deployed and exceeded? if(i_fir_data.isBitSet(BUS0_MAX_SPARES_EXCEEDED,1) || i_fir_data.isBitSet(BUS1_MAX_SPARES_EXCEEDED,1) || i_fir_data.isBitSet(BUS2_MAX_SPARES_EXCEEDED,1) || i_fir_data.isBitSet(BUS3_MAX_SPARES_EXCEEDED,1) || i_fir_data.isBitSet(BUS4_MAX_SPARES_EXCEEDED,1)){ if(o_rc) fapiLogError(o_rc); o_rc=io_fir_max_spares_exceeded_isolation(i_target,i_chip_interface,i_current_group); } //recalibration error if(i_fir_data.isBitSet(BUS0_RECALIBRATION_ERROR,1) || i_fir_data.isBitSet(BUS1_RECALIBRATION_ERROR,1) || i_fir_data.isBitSet(BUS2_RECALIBRATION_ERROR,1) || i_fir_data.isBitSet(BUS3_RECALIBRATION_ERROR,1) || i_fir_data.isBitSet(BUS4_RECALIBRATION_ERROR,1)){ if(o_rc) fapiLogError(o_rc); o_rc=io_fir_recal_error_isolation(i_target,i_chip_interface,i_current_group); } //too many bus errors if(i_fir_data.isBitSet(BUS0_TOO_MANY_BUS_ERRORS,1) || i_fir_data.isBitSet(BUS1_TOO_MANY_BUS_ERRORS,1) || i_fir_data.isBitSet(BUS2_TOO_MANY_BUS_ERRORS,1) || i_fir_data.isBitSet(BUS3_TOO_MANY_BUS_ERRORS,1) || i_fir_data.isBitSet(BUS4_TOO_MANY_BUS_ERRORS,1)){ if(o_rc) fapiLogError(o_rc); o_rc=io_fir_too_many_bus_err_isolation(i_target,i_chip_interface,i_current_group); } return(o_rc); } ReturnCode io_fir_isolation(const fapi::Target &i_target){ ReturnCode o_rc; uint32_t rc_ecmd=0; fir_io_interface_t interface; io_interface_t gcr_interface; // requires different base address for gcr scoms uint32_t group; ecmdDataBufferBase fir_data(64); rc_ecmd|=fir_data.flushTo0(); //rc_ecmd|=fir_data.setBitLength(64); //on dmi if( (i_target.getType() == fapi::TARGET_TYPE_MCS_CHIPLET )){ FAPI_DBG("This is a Processor DMI bus using base DMI scom address"); interface=FIR_CP_IOMC0_P0; // base scom for MC bus gcr_interface=CP_IOMC0_P0; o_rc=read_fir_reg(i_target,interface,fir_data); group=3; if(o_rc) return(o_rc); o_rc=io_error_isolation(i_target,gcr_interface,group,fir_data); } //on cen side else if((i_target.getType() == fapi::TARGET_TYPE_MEMBUF_CHIP)){ FAPI_DBG("This is a Centaur DMI bus using base DMI scom address"); interface=FIR_CEN_DMI; gcr_interface=CEN_DMI; o_rc=read_fir_reg(i_target,interface,fir_data); group=0; if(o_rc) return(o_rc); o_rc=io_error_isolation(i_target,gcr_interface,group,fir_data); } // on x bus else if((i_target.getType() == fapi::TARGET_TYPE_XBUS_ENDPOINT)){ FAPI_DBG("This is a X Bus invocation"); interface=FIR_CP_FABRIC_X0; gcr_interface=CP_FABRIC_X0; o_rc=read_fir_reg(i_target,interface,fir_data); group=0; if(o_rc) return(o_rc); o_rc=io_error_isolation(i_target,gcr_interface,group,fir_data); } //on a bus else if((i_target.getType() == fapi::TARGET_TYPE_ABUS_ENDPOINT)){ FAPI_DBG("This is an A Bus invocation"); interface=FIR_CP_FABRIC_A0; gcr_interface=CP_FABRIC_A0; o_rc=read_fir_reg(i_target,interface,fir_data); group=0; if(o_rc) return(o_rc); o_rc=io_error_isolation(i_target,gcr_interface,group,fir_data); } else{ FAPI_ERR("Invalid io_clear_firs HWP invocation . Target doesnt belong to DMI/X/A instances"); FAPI_SET_HWP_ERROR(o_rc, IO_CLEAR_FIRS_INVALID_INVOCATION_RC); } return(o_rc); //the last error needs to be logged in the wrapper code if there is one. } }