src/occ_gpe1/gpe1_dimm_control.c
/*
 * Function Specifications:
 *
 * Name: gpe_reset_mem_deadman
 *
 * Description:  Read memory performance counter for one MCA.
 *               This effectively resets the memory deadman timer
 *
 * Inputs:       cmd is a pointer to IPC msg's cmd and cmd_data struct
 *
 * Outputs:      error: sets rc, address, and ffdc in the cmd_data's
 *                      GpeErrorStruct
 *
 * End Function Specification
 */
Function Specifications:
Name: gpe_reset_mem_deadman

Read memory performance counter for one MCA.
This effectively resets the memory deadman timer

cmd is a pointer to IPC msg's cmd and cmd_data struct

sets rc, address, and ffdc in the cmd_data's
GpeErrorStruct

End Function Specification
Function Specifications : Name : gpe_reset_mem_deadman Read memory performance counter for one MCA . This effectively resets the memory deadman timer cmd is a pointer to IPC msg ' s cmd and cmd_data struct sets rc address and ffdc in the cmd_data ' s GpeErrorStruct End Function Specification
void gpe_reset_mem_deadman(ipc_msg_t* cmd, void* arg)
{
    static bool L_init_complete[NUM_NIMBUS_MCAS] = {FALSE};
    int      rc = 0;
    uint64_t regValue; 
    ipc_async_cmd_t *async_cmd = (ipc_async_cmd_t*)cmd;
    reset_mem_deadman_args_t *args = (reset_mem_deadman_args_t*)async_cmd->cmd_data;
    args->error.error = 0;
    args->error.ffdc = 0;
    do
    {
        int mca = args->mca; 
        if(!L_init_complete[mca])
        {
            rc = getscom_abs(STR_REG0_MCA(mca), &regValue);
            if(rc)
            {
                PK_TRACE("gpe_reset_mem_deadman: Failed to read STR0 to program deadman timer"
                         " MCA:0x%08x, Address:0x%08x, rc:0x%08x", mca, STR_REG0_MCA(mca), rc);
                gpe_set_ffdc(&(args->error), STR_REG0_MCA(mca),
                             GPE_RC_SCOM_GET_FAILED, rc);
                break;
            }
            regValue |= 0x0000000000000040;
            regValue &= ~(0x0000000000000038);
            rc = putscom_abs(STR_REG0_MCA(mca), regValue);
            if(rc)
            {
                PK_TRACE("gpe_reset_mem_deadman: Failed to program deadman timer (STR REG0)"
                         " MCA:0x%08x, Data:0x%08x, rc:0x%08x", mca, (uint32_t)regValue, rc);
                gpe_set_ffdc(&(args->error), STR_REG0_MCA(mca),
                             GPE_RC_SCOM_PUT_FAILED, rc);
                break;
            }
        }
        rc = getscom_abs(PERF_MON_COUNTS_IDLE_MCA(mca), &regValue);
        if(rc)
        {
            PK_TRACE("gpe_reset_mem_deadman: Performance Monitor Counts read failed"
                     " MCA:0x%08x, Address:0x%08x, rc:0x%08x",
                     mca, PERF_MON_COUNTS_IDLE_MCA(mca), rc);
            gpe_set_ffdc(&(args->error), PERF_MON_COUNTS_IDLE_MCA(mca),
                         GPE_RC_SCOM_GET_FAILED, rc);
            break;
        }
        else
        {
            args->idle_counts.med_idle_cnt = ((regValue & 0xFFFFFFFF00000000) >> 32);
            args->idle_counts.high_idle_cnt = (regValue & 0xFFFFFFFF);
        }
        if(!L_init_complete[mca])
        {
            L_init_complete[mca] = TRUE; 
            rc = getscom_abs(ER_THROTTLE_MCA(mca), &regValue);
            if(rc)
            {
                PK_TRACE("gpe_reset_mem_deadman: Failed to read emergency throttle register"
                         " MCA:0x%08x, Address:0x%08x, rc:0x%08x", mca, ER_THROTTLE_MCA(mca), rc);
                gpe_set_ffdc(&(args->error), ER_THROTTLE_MCA(mca), GPE_RC_SCOM_GET_FAILED, rc);
                break;
            }
            if(regValue & ER_THROTTLE_IN_PROGRESS_MASK)
            {
                PK_TRACE("gpe_reset_mem_deadman: Enabled timer and clearing throttle for MCA:0x%08x", mca);
                regValue &= ~(ER_THROTTLE_IN_PROGRESS_MASK);
                rc = putscom_abs(ER_THROTTLE_MCA(mca), regValue);
                if(rc)
                {
                    PK_TRACE("gpe_reset_mem_deadman: Failed to clear emergency throttle"
                             " MCA:0x%08x, rc:0x%08x", mca, rc);
                    gpe_set_ffdc(&(args->error), ER_THROTTLE_MCA(mca), GPE_RC_SCOM_PUT_FAILED, rc);
                    break;
                }
                rc = getscom_abs(MCA_CAL_FIR_REG_MCA(mca), &regValue);
                if(rc)
                {
                    PK_TRACE("gpe_reset_mem_deadman: Failed to read MCA FIR register"
                             " MCA:0x%08x, Address:0x%08x, rc:0x%08x",
                             mca, MCA_CAL_FIR_REG_MCA(mca), rc);
                    gpe_set_ffdc(&(args->error), MCA_CAL_FIR_REG_MCA(mca), GPE_RC_SCOM_GET_FAILED, rc);
                    break;
                }
                regValue &= ~(MCA_FIR_THROTTLE_ENGAGED_MASK);
                rc = putscom_abs(MCA_CAL_FIR_REG_MCA(mca), regValue);
                if(rc)
                {
                    PK_TRACE("gpe_reset_mem_deadman: Failed to clear emergency throttle FIR bit"
                             " MCA:0x%08x, rc:0x%08x", mca, rc);
                    gpe_set_ffdc(&(args->error), MCA_CAL_FIR_REG_MCA(mca), GPE_RC_SCOM_PUT_FAILED, rc);
                    break;
                }
            }
            else
            {
                PK_TRACE("gpe_reset_mem_deadman: Enabled timer for MCA:0x%08x", mca);
            }
        }  
        rc = getscom_abs(PERF_MON_COUNTS0_MCA(mca), &regValue);
        if(rc)
        {
            PK_TRACE("gpe_reset_mem_deadman: Performance Monitor Counts0 read failed"
                     " MCA:0x%08x, Address:0x%08x, rc:0x%08x",
                     mca, PERF_MON_COUNTS0_MCA(mca), rc);
            gpe_set_ffdc(&(args->error), PERF_MON_COUNTS0_MCA(mca),
                         GPE_RC_SCOM_GET_FAILED, rc);
            break;
        }
        else
        {
            args->rd_wr_counts.mba_read_cnt = ((regValue & 0xFFFFFFFF00000000) >> 32);
            args->rd_wr_counts.mba_write_cnt = (regValue & 0xFFFFFFFF);
        }
    } while(0);
    rc = ipc_send_rsp(cmd, IPC_RC_SUCCESS);
    if(rc)
    {
        PK_TRACE("gpe_reset_mem_deadman: Failed to send response back. Halting GPE1", rc);
        gpe_set_ffdc(&(args->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc);
        pk_halt();
    }
}
void gpe_reset_mem_deadman ( ipc_msg_t * cmd , void * arg ) { static bool L_init_complete [ NUM_NIMBUS_MCAS ] = { FALSE } ; int rc = 0 ; uint64_t regValue ; ipc_async_cmd_t * async_cmd = ( ipc_async_cmd_t * ) cmd ; reset_mem_deadman_args_t * args = ( reset_mem_deadman_args_t * ) async_cmd -> cmd_data ; args -> error . error = 0 ; args -> error . ffdc = 0 ; do { int mca = args -> mca ; if ( ! L_init_complete [ mca ] ) { rc = getscom_abs ( STR_REG0_MCA ( mca ) , & regValue ) ; if ( rc ) { PK_TRACE ( " " " " , mca , STR_REG0_MCA ( mca ) , rc ) ; gpe_set_ffdc ( & ( args -> error ) , STR_REG0_MCA ( mca ) , GPE_RC_SCOM_GET_FAILED , rc ) ; break ; } regValue |= 0x0000000000000040 ; regValue &= ~ ( 0x0000000000000038 ) ; rc = putscom_abs ( STR_REG0_MCA ( mca ) , regValue ) ; if ( rc ) { PK_TRACE ( " " " " , mca , ( uint32_t ) regValue , rc ) ; gpe_set_ffdc ( & ( args -> error ) , STR_REG0_MCA ( mca ) , GPE_RC_SCOM_PUT_FAILED , rc ) ; break ; } } rc = getscom_abs ( PERF_MON_COUNTS_IDLE_MCA ( mca ) , & regValue ) ; if ( rc ) { PK_TRACE ( " " " " , mca , PERF_MON_COUNTS_IDLE_MCA ( mca ) , rc ) ; gpe_set_ffdc ( & ( args -> error ) , PERF_MON_COUNTS_IDLE_MCA ( mca ) , GPE_RC_SCOM_GET_FAILED , rc ) ; break ; } else { args -> idle_counts . med_idle_cnt = ( ( regValue & 0xFFFFFFFF00000000 ) >> 32 ) ; args -> idle_counts . high_idle_cnt = ( regValue & 0xFFFFFFFF ) ; } if ( ! L_init_complete [ mca ] ) { L_init_complete [ mca ] = TRUE ; rc = getscom_abs ( ER_THROTTLE_MCA ( mca ) , & regValue ) ; if ( rc ) { PK_TRACE ( " " " " , mca , ER_THROTTLE_MCA ( mca ) , rc ) ; gpe_set_ffdc ( & ( args -> error ) , ER_THROTTLE_MCA ( mca ) , GPE_RC_SCOM_GET_FAILED , rc ) ; break ; } if ( regValue & ER_THROTTLE_IN_PROGRESS_MASK ) { PK_TRACE ( " " , mca ) ; regValue &= ~ ( ER_THROTTLE_IN_PROGRESS_MASK ) ; rc = putscom_abs ( ER_THROTTLE_MCA ( mca ) , regValue ) ; if ( rc ) { PK_TRACE ( " " " " , mca , rc ) ; gpe_set_ffdc ( & ( args -> error ) , ER_THROTTLE_MCA ( mca ) , GPE_RC_SCOM_PUT_FAILED , rc ) ; break ; } rc = getscom_abs ( MCA_CAL_FIR_REG_MCA ( mca ) , & regValue ) ; if ( rc ) { PK_TRACE ( " " " " , mca , MCA_CAL_FIR_REG_MCA ( mca ) , rc ) ; gpe_set_ffdc ( & ( args -> error ) , MCA_CAL_FIR_REG_MCA ( mca ) , GPE_RC_SCOM_GET_FAILED , rc ) ; break ; } regValue &= ~ ( MCA_FIR_THROTTLE_ENGAGED_MASK ) ; rc = putscom_abs ( MCA_CAL_FIR_REG_MCA ( mca ) , regValue ) ; if ( rc ) { PK_TRACE ( " " " " , mca , rc ) ; gpe_set_ffdc ( & ( args -> error ) , MCA_CAL_FIR_REG_MCA ( mca ) , GPE_RC_SCOM_PUT_FAILED , rc ) ; break ; } } else { PK_TRACE ( " " , mca ) ; } } rc = getscom_abs ( PERF_MON_COUNTS0_MCA ( mca ) , & regValue ) ; if ( rc ) { PK_TRACE ( " " " " , mca , PERF_MON_COUNTS0_MCA ( mca ) , rc ) ; gpe_set_ffdc ( & ( args -> error ) , PERF_MON_COUNTS0_MCA ( mca ) , GPE_RC_SCOM_GET_FAILED , rc ) ; break ; } else { args -> rd_wr_counts . mba_read_cnt = ( ( regValue & 0xFFFFFFFF00000000 ) >> 32 ) ; args -> rd_wr_counts . mba_write_cnt = ( regValue & 0xFFFFFFFF ) ; } } while ( 0 ) ; rc = ipc_send_rsp ( cmd , IPC_RC_SUCCESS ) ; if ( rc ) { PK_TRACE ( " " , rc ) ; gpe_set_ffdc ( & ( args -> error ) , 0x00 , GPE_RC_IPC_SEND_FAILED , rc ) ; pk_halt ( ) ; } }
Function Specifications:
 Name: gpe_reset_mem_deadman
Function Specifications : Name : gpe_reset_mem_deadman
// Note: arg was set to 0 in ipc func table (ipc_func_tables.c), so don't use it. // the ipc arguments passed through the ipc_msg_t structure, has a pointer // to the reset_mem_deadman_args_t struct. // a pointer to hold get/put SCOM register value // Nimbus MCA; mc_pair = mca >>2 and port = mca & 3 // Part of init is to enable the deadman timer for this MCA // Read STR Register 0 // set the deadman timer to the max value: bits 57:60 = 0b1000 // Write Modified STR Register 0 // The "Deadman" timer is reset by reading from this performance monitor counts register // Now that we are poking the deadman timer as second part of init check for and clear // any previous emergency throttle that may have happened from the last time OCC was running // Done handling initialization // Read Emergency Throttle Register // clear Emergency Throttle In-Progress bit if set, this is indication that OCC has been // re-started from permanent safe mode without an IPL // Write Modified Emergency Throttle Register // Clear the emergency throttle engaged FIR bit // Write Modified MCA FIR Register // if !L_init_complete // In addition to resetting the "deadman" counter, get some performance information // send back a response, IPC success even if ffdc/rc are non zeros