/** brief handle chip attentions * * @param[in] i_proc - processor chip id at attention * XSCOM chip id based on devtree defn * @param[in] i_ipollStatus - processor chip Ipoll status * @param[in] i_ipollMask - processor chip Ipoll mask * @return 0 on success else return code */ int handleAttns(uint64_t i_proc, uint64_t i_ipollStatus, uint64_t i_ipollMask) { ATTN_SLOW(ENTER_MRK"ATTN_RT::handleAttns RtProc: %llx" ", ipollMask: %llx, ipollStatus: %llx", i_proc, i_ipollMask, i_ipollStatus); int rc = 0; errlHndl_t err = NULL; AttentionList attentions; MemOps & memOps = getMemOps(); uint64_t l_iprScomData = 0; do { // Convert chipIds to HB targets TargetHandle_t proc = NULL; err = RT_TARG::getHbTarget(i_proc, proc); if(err) { ATTN_ERR("ATTN_RT::handleAttns getHbTarget " "returned error for RtProc: %llx", i_proc); rc = EINVAL; break; } err = Singleton<Service>::instance().handleAttentions(proc); if(err) { ATTN_ERR("ATTN_RT::handleAttns service::handleAttentions " "returned error for RtProc: %llx", i_proc); break; } // For host attentions, clear gpio interrupt type register. // If we do not clear gpio register, ipoll status will again // get set and we will end up in infinite loop. uint64_t hostMask = 0; IPOLL::getCheckbits(HOST, hostMask); if( i_ipollMask & hostMask) { // After handling attn, check GP1 for more attns // as there could be additional memory units with attns. attentions.clear(); err = memOps.resolve(proc, attentions); if(err) { ATTN_ERR("RT GP1 Chk:memOps returned error.HUID:0X%08X ", get_huid( proc )); break; } // Save the IPR if any attns still active on Centaurs if (!attentions.empty()) { err = getScom(proc, INTR_TYPE_LCL_ERR_STATUS_REG, l_iprScomData); if(err) { ATTN_ERR("RT SaveIPR returned error.HUID:0X%08X ", get_huid( proc )); break; } } // end if any attentions // Clear the IPR (interrupt presentation register) err = putScom(proc, INTR_TYPE_LCL_ERR_STATUS_AND_REG, 0); if(err) { ATTN_ERR("ATTN_RT::handleAttns putscom failed for " "RtProc: %llx address:0x%08X", i_proc, INTR_TYPE_LCL_ERR_STATUS_AND_REG); break; } // Restore the IPR if any attns still active in Centaurs if (!attentions.empty()) { err = putScom(proc, INTR_TYPE_LCL_ERR_STATUS_OR_REG, l_iprScomData); if(err) { ATTN_ERR("RT RestoreIPR returned error.HUID:0X%08X ", get_huid( proc )); break; } } // end if any attentions } // end if i_ipollMask & hostMask) } while(0); if(err) { errlCommit( err, ATTN_COMP_ID ); if(0 == rc) { rc = -1; } } attentions.clear(); ATTN_SLOW(EXIT_MRK"ATTN_RT::handleAttns rc: %d", rc); return rc; }
errlHndl_t Service::configureInterrupts( msg_q_t i_q, ConfigureMode i_mode) { errlHndl_t err = NULL; // First register for Q // This will set up the psi host bridge logic for // lcl_err interrupt on all chips if(i_mode == UP) { err = INTR::registerMsgQ(i_q, ATTENTION, INTR::ISN_LCL_ERR); } // setup the ITR macro for GPIO type host attentions, // on all procs if(!err) { TargetHandleList procs; getTargetService().getAllChips(procs, TYPE_PROC); TargetHandleList::iterator it = procs.begin(); while(it != procs.end()) { uint64_t mask = 0; // clear GPIO interrupt type status register if(i_mode == UP) { err = putScom(*it, INTR_TYPE_LCL_ERR_STATUS_AND_REG, 0); } if(err) { break; } // unmask GPIO interrupt type mask = 0x8000000000000000ull; err = putScom( *it, (i_mode == UP ? INTR_TYPE_MASK_AND_REG : INTR_TYPE_MASK_OR_REG), i_mode == UP ? ~mask : mask); if(err) { break; } // set GPIO interrupt type mode - or if(i_mode == UP) { err = putScom(*it, INTR_TYPE_CONFIG_AND_REG, ~mask); } if(err) { break; } // enable/disable MCSes mask = 0; GP1::forEach(~0, &mask, &getPbGp2Mask); err = modifyScom( *it, GP2_REG, i_mode == UP ? mask : ~mask, i_mode == UP ? SCOM_OR : SCOM_AND); if(err) { break; } // enable attentions in ipoll mask mask = HostMask::nonHost(); mask |= HostMask::host(); // this doesn't have an and/or reg for some reason... err = modifyScom( *it, IPOLL::address, i_mode == UP ? ~mask : mask, i_mode == UP ? SCOM_AND : SCOM_OR); if(err) { break; } ++it; } if(!err && i_mode == DOWN) { if(NULL == INTR::unRegisterMsgQ(INTR::ISN_LCL_ERR)) { ATTN_ERR("INTR did not find isn: 0x%07x", INTR::ISN_LCL_ERR); } } } return err; }
errlHndl_t FakePrd::callPrd(const AttentionList & i_attentions) { errlHndl_t l_elog = i_attentions.forEach(Clear(*iv_injectSink)).err; AttnList l_attnList; i_attentions.getAttnList(l_attnList); ATTN_TRACE("fakeCallPrd with Attn Count of %d", l_attnList.size()); // ----------------------------------------------------- // This is FAKE code only. // If you do the EC/MODEL check, it crashes in CXX testcase. // Kind of thinking some library missing that is needed when // adding these calls, For now, I will just leave them out // and we could probably scrap this test now that it runs // successfully (see attntestproc.H) // (Maybe add to 'fake target service' for these ATTRs) // ----------------------------------------------------- // For the initial NIMBUS chip, there is a HW issue // which requires us to clear the "Combined Global // interrupt register" on recoverable errors. // This also affects Checkstop/Special Attns, but // the FSP handles those and already clears the reg. // The issue does not apply to host/unit cs attns. // uint8_t l_ecLevel = 0; AttnList::iterator l_attnIter = l_attnList.begin(); // Shouldn't be mixing NIMBUS with CUMULUS,etc... // so probably don't need to repeat this call per chip. // bool l_isNimbus = ( (*l_attnIter).targetHndl-> // getAttr<ATTR_MODEL>() == MODEL_NIMBUS ); // Iterate thru all chips in case PRD handled // a chip other than the first one. while(l_attnIter != l_attnList.end()) { // l_ecLevel = (*l_attnIter).targetHndl->getAttr<ATTR_EC>(); if ( (RECOVERABLE == (*l_attnIter).attnType) // && (true == l_isNimbus) && (l_ecLevel < 0x11) ) { errlHndl_t l_scomErr = NULL; uint64_t l_clrAllBits = 0; l_scomErr = putScom( (*l_attnIter).targetHndl, PIB_INTR_TYPE_REG, l_clrAllBits ); if (NULL != l_scomErr) { ATTN_ERR("Clear PibIntrReg failed, HUID:0X%08X", get_huid( (*l_attnIter).targetHndl) ); errlCommit(l_scomErr, ATTN_COMP_ID); } // failed to clear PIB intr reg } // if recoverable attn ++l_attnIter; } // end while looping thru attn list return l_elog; }