diff options
Diffstat (limited to 'src/sbefw/sbecmdprocessor.C')
-rw-r--r-- | src/sbefw/sbecmdprocessor.C | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/src/sbefw/sbecmdprocessor.C b/src/sbefw/sbecmdprocessor.C new file mode 100644 index 00000000..6a945b4a --- /dev/null +++ b/src/sbefw/sbecmdprocessor.C @@ -0,0 +1,376 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/sbefw/sbecmdprocessor.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +/* + * @file: ppe/sbe/sbefw/sbecmdprocessor.C + * + * @brief This file contains the SBE Command processing Thread Routines + * + */ + + +#include "sbeexeintf.H" +#include "sbefifo.H" +#include "sbecmdparser.H" +#include "sbeirq.H" +#include "sbetrace.H" +#include "sbe_sp_intf.H" +#include "assert.h" +#include "sbeFifoMsgUtils.H" +#include "sbeerrorcodes.H" +#include "sbeHostUtils.H" +#include "sbeHostMsg.H" +#include "sbecmdiplcontrol.H" +#include "sberegaccess.H" +#include "sbestates.H" +#include "fapi2.H" + + +///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// +void sbeHandlePsuResponse (const uint32_t i_rc) +{ + #define SBE_FUNC " sbeHandlePsuResponse " + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + + do + { + uint8_t l_cnt = 0; + switch (i_rc) + { + case SBE_SEC_COMMAND_CLASS_NOT_SUPPORTED: + case SBE_SEC_COMMAND_NOT_SUPPORTED: + case SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE: + // Caller sent an invalid Command class/opcode + // Set the Ack bit in SBE->PSU DB register + l_rc = sbeAcknowledgeHost(); + if (SBE_SEC_OPERATION_SUCCESSFUL != l_rc) + { + break; + } + // Set primary and secondary status + g_sbeSbe2PsuRespHdr.setStatus(SBE_PRI_INVALID_COMMAND, i_rc); + + // Now Update SBE->PSU Mbx Reg4 with response + l_cnt = sizeof(g_sbeSbe2PsuRespHdr)/ + sizeof(uint64_t); + l_rc = sbeWriteSbe2PsuMbxReg(SBE_HOST_PSU_MBOX_REG4, + reinterpret_cast<const uint64_t *>( + &g_sbeSbe2PsuRespHdr), l_cnt, true); + break; + + case SBE_SEC_OS_FAILURE: + // Set primary and secondary status + g_sbeSbe2PsuRespHdr.setStatus(SBE_PRI_GENERIC_EXECUTION_FAILURE, + i_rc); + + // Now Update SBE->PSU Mbx Reg4 with response + l_cnt = sizeof(g_sbeSbe2PsuRespHdr)/ + sizeof(uint64_t); + l_rc = sbeWriteSbe2PsuMbxReg(SBE_HOST_PSU_MBOX_REG4, + reinterpret_cast<const uint64_t *>( + &g_sbeSbe2PsuRespHdr), l_cnt, true); + break; + + case SBE_SEC_OPERATION_SUCCESSFUL: + // Services code successfully executed the chipOp. + SBE_INFO(SBE_FUNC"PSU ChipOp Done"); + break; + + default: + // The only possibility (as of now) to reach till this point + // is when there was a mbx register access (scom) failure + // happened. Going to return to the waiting loop. + break; + } + } while(false); + + #undef SBE_FUNC +} + + +///////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////// +void sbeHandleFifoResponse (const uint32_t i_rc) +{ + #define SBE_FUNC " sbeHandleFifoResponse " + SBE_ENTER(SBE_FUNC); + + do + { + uint16_t l_primStatus = SBE_PRI_OPERATION_SUCCESSFUL; + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + + // Handle FIFO reset case + if (i_rc == SBE_FIFO_RESET_RECEIVED) + { + break; + } + + if ( (i_rc == SBE_SEC_UNEXPECTED_EOT_INSUFFICIENT_DATA) || + (i_rc == SBE_SEC_UNEXPECTED_EOT_EXCESS_DATA) ) + { + l_primStatus = SBE_PRI_INVALID_DATA; + } + + uint32_t l_len2dequeue = 0; + uint32_t l_dist2StatusHdr = 0; + uint32_t l_sbeDownFifoRespBuf[4] = {0}; + uint32_t l_secStatus = i_rc; + + switch (i_rc) + { + case SBE_SEC_COMMAND_CLASS_NOT_SUPPORTED: + case SBE_SEC_COMMAND_NOT_SUPPORTED: + case SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE: + // Caller sent Invalid Command + + case SBE_SEC_OS_FAILURE: + // PK API Failures + + // Flush out the upstream FIFO till EOT arrives + l_len2dequeue = 1; + l_rc = sbeUpFifoDeq_mult (l_len2dequeue, NULL, + true, true); + + if ( (l_rc == SBE_FIFO_RESET_RECEIVED) || + (l_rc == SBE_SEC_FIFO_ACCESS_FAILURE) ) + { + break; + } + + if (l_rc) + { + l_secStatus = l_rc; + } + + // Don't break here to force the flow through + // the next case to enqueue the response into + // the downstream FIFO + + case SBE_SEC_UNEXPECTED_EOT_INSUFFICIENT_DATA: + case SBE_SEC_UNEXPECTED_EOT_EXCESS_DATA: + // EOT arrived prematurely in upstream FIFO + // or there were unexpected data in upstream FIFO + + SBE_ERROR(SBE_FUNC"Operation failure, " + "l_primStatus[0x%08X], " + "l_secStatus[0x%08X]", + l_primStatus, l_secStatus); + + sbeBuildMinRespHdr(&l_sbeDownFifoRespBuf[0], + l_dist2StatusHdr, + l_primStatus, + l_secStatus, + 0); + l_rc = sbeDownFifoEnq_mult (++l_dist2StatusHdr, + &l_sbeDownFifoRespBuf[0]); + if (l_rc) + { + SBE_ERROR(SBE_FUNC"sbeDownFifoEnq_mult failure," + " l_rc[0x0%08X]", l_rc); + // not attempting to signal EOT + break; + } + // Follow through to signal EOT in downstream + + case SBE_SEC_OPERATION_SUCCESSFUL: // Successful execution + // Signal EOT in Downstream FIFO + l_rc = sbeDownFifoSignalEot(); + if (l_rc) + { + SBE_ERROR(SBE_FUNC"sbeDownFifoSignalEot failure," + " l_rc[0x0%08X]", l_rc); + } + SBE_INFO(SBE_FUNC"ChipOp Done"); + break; + + default: + break; + } + } while (false); + + #undef SBE_FUNC +} + + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +void sbeSyncCommandProcessor_routine(void *i_pArg) +{ + #define SBE_FUNC " sbeSyncCommandProcessor_routine " + SBE_ENTER(SBE_FUNC); + + // Check the destination bit at the start + if(SbeRegAccess::theSbeRegAccess().isIstepMode()) + { + // In this state, we need not take care of FFDC State, User may + // or may not fetch FFDC and may not issue sbeContinueboot + SBE_INFO(SBE_FUNC"Continuous IPL mode not set, will wait for " + "commands..."); + (void)SbeRegAccess::theSbeRegAccess(). + updateSbeState(SBE_STATE_ISTEP); + } + // If Istep mode is not set, it makes sense to check if we are directly + // in runtime. + else if(true == SbeRegAccess::theSbeRegAccess().isDestBitRuntime()) + { + SBE_INFO(SBE_FUNC"Destination bit tells us to go to runtime"); + (void)SbeRegAccess::theSbeRegAccess(). + updateSbeState(SBE_STATE_RUNTIME); + } + // Now we can assume that we are in Continuous IPL mode, just check if + // FFDC needs to be collected before continuing with IPL + else if(true == SbeRegAccess::theSbeRegAccess().isCollectFFDCSet()) + { + SBE_INFO(SBE_FUNC"FFDC Collect State - Waiting for FFDC to be picked"); + (void)SbeRegAccess::theSbeRegAccess(). + updateSbeState(SBE_STATE_FFDC_COLLECT); + } + else + { + SBE_INFO(SBE_FUNC"Continuous IPL Mode set... IPLing"); + (void)SbeRegAccess::theSbeRegAccess(). + updateSbeState(SBE_STATE_IPLING); + sbeDoContinuousIpl(); + } + + do + { + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + + // Wait for new command processing + int l_rcPk = pk_semaphore_pend ( + &g_sbeSemCmdProcess, PK_WAIT_FOREVER); + + do + { + // Local Variables + uint8_t l_cmdClass = 0; + uint8_t l_cmdOpCode = 0; + + // Reset the value of fapi2::current_err from previous value. + // This is required as none of procedure set this value in success + // case. So if we do not reset previous value, previous failure + // will impact new chipops also. + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + // Check on the Rx Thread Interrupt Bits for Interrupt Status + if ( g_sbeIntrSource.isSet(SBE_RX_ROUTINE, + SBE_INTERFACE_PSU) ) + { + l_rc = g_sbeSbe2PsuRespHdr.secStatus; + l_cmdClass = g_sbePsu2SbeCmdReqHdr.cmdClass; + l_cmdOpCode = g_sbePsu2SbeCmdReqHdr.command; + // Set this here, so that during response handling we know which + // interrupt we are processing, need not check for + // g_sbeIntrSource again + g_sbeIntrSource.setIntrSource(SBE_PROC_ROUTINE, + SBE_INTERFACE_PSU); + } + else if ( g_sbeIntrSource.isSet(SBE_RX_ROUTINE, + SBE_INTERFACE_FIFO) ) + { + l_rc = g_sbeCmdRespHdr.sec_status; + l_cmdClass = g_sbeFifoCmdHdr.cmdClass; + l_cmdOpCode = g_sbeFifoCmdHdr.command; + // Set this here, so that during response handling we know which + // interrupt we are processing, need not check for + // g_sbeIntrSource again + g_sbeIntrSource.setIntrSource(SBE_PROC_ROUTINE, + SBE_INTERFACE_FIFO); + } + else // SBE_INTERFACE_FIFO_RESET or SBE_INTERFACE_UNKNOWN + { + SBE_ERROR(SBE_FUNC"Unexpected interrupt communicated to the " + "processor thread. Interrupt source: 0x%02X 0x%02X", + g_sbeIntrSource.intrSource, g_sbeIntrSource.rxThrIntrSource); + assert(false); + break; + } + + // PK API failure + if (l_rcPk != PK_OK) + { + SBE_ERROR(SBE_FUNC"pk_semaphore_pend failed, " + "l_rcPk=%d, g_sbeSemCmdRecv.count=%d", + l_rcPk, g_sbeSemCmdRecv.count); + + // If it's a semphore_pend error then update the same to show + // internal failure + l_rc = SBE_SEC_OS_FAILURE; + } + + // Check for error which Receiver thread might have set + if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) + { + break; + } + + // Get the command function + sbeCmdFunc_t l_pFuncP = sbeFindCmdFunc (l_cmdClass, l_cmdOpCode); + assert( l_pFuncP ) + + // Call the ChipOp function + l_rc = l_pFuncP ((uint8_t *)i_pArg); + + } while(false); // Inner do..while loop ends here + + SBE_INFO (SBE_FUNC"New cmd arrived, g_sbeSemCmdProcess.count=%d " + "l_rc=[0x%04X]", + g_sbeSemCmdProcess.count, l_rc); + + if ( g_sbeIntrSource.isSet(SBE_PROC_ROUTINE, SBE_INTERFACE_PSU) ) + { + sbeHandlePsuResponse (l_rc); + + // Enable Host interrupt + g_sbeIntrSource.clearIntrSource(SBE_ALL_HANDLER,SBE_INTERFACE_PSU); + pk_irq_enable(SBE_IRQ_HOST_PSU_INTR); + } + else if ( g_sbeIntrSource.isSet(SBE_PROC_ROUTINE, SBE_INTERFACE_FIFO) ) + { + sbeHandleFifoResponse (l_rc); + + // Enable the new data available interrupt + g_sbeIntrSource.clearIntrSource(SBE_ALL_HANDLER,SBE_INTERFACE_FIFO); + pk_irq_enable(SBE_IRQ_SBEFIFO_DATA); + pk_irq_enable(SBE_IRQ_SBEFIFO_RESET); + } + } while(true); // Thread always exists + SBE_EXIT(SBE_FUNC); +} + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +void sbeAsyncCommandProcessor_routine(void *arg) +{ + SBE_INFO("sbeAsyncCommandProcessor Thread started"); + + do + { + // @TODO RTC via : 130392 + // Add infrastructure for host interface + + } while(0); +} |