void Service::processAttentions(const TargetHandleList & i_procs) { errlHndl_t err = NULL; AttentionList attentions; MemOps & memOps = getMemOps(); ProcOps & procOps = getProcOps(); do { attentions.clear(); // enumerate the highest priority pending attention // on every chip and then give the entire set to PRD TargetHandleList::const_iterator pit = i_procs.end(); while(pit-- != i_procs.begin()) { // enumerate proc local attentions (xstp,spcl,rec). err = procOps.resolveIpoll(*pit, attentions); if(err) { errlCommit(err, ATTN_COMP_ID); } // enumerate host attentions and convert // to centaur targets err = memOps.resolve(*pit, attentions); if(err) { errlCommit(err, ATTN_COMP_ID); } } err = getPrdWrapper().callPrd(attentions); if(err) { errlCommit(err, ATTN_COMP_ID); } // unmask proc local attentions // (xstp,rec,special) in ipoll mask // any pending attentions will be found // on the next pass pit = i_procs.end(); while(pit-- != i_procs.begin()) { mutex_lock(&iv_mutex); // the other thread might be trying to mask // on the same target. The mutex ensures // neither thread corrupts the register. err = modifyScom( *pit, IPOLL::address, ~HostMask::nonHost(), SCOM_AND); mutex_unlock(&iv_mutex); if(err) { errlCommit(err, ATTN_COMP_ID); } } // if on a given Centaur with a pending attention // on an MBA, an attention comes on in the other MBA // we don't get an interrupt for that. So make another // pass and check for that. } while(!attentions.empty()); }
void Service::processIntrQMsgPreAck(const msg_t & i_msg) { // this function should do as little as possible // since the hw can't generate additional interrupts // until the msg is acknowledged TargetHandle_t proc = NULL; INTR::XISR_t xisr; xisr.u32 = i_msg.data[0]; TargetHandleList procs; getTargetService().getAllChips(procs, TYPE_PROC); TargetHandleList::iterator it = procs.begin(); // resolve the xisr to a proc target while(it != procs.end()) { uint64_t node = 0, chip = 0; getTargetService().getAttribute(ATTR_FABRIC_NODE_ID, *it, node); getTargetService().getAttribute(ATTR_FABRIC_CHIP_ID, *it, chip); if(node == xisr.node && chip == xisr.chip) { proc = *it; break; } ++it; } uint64_t hostMask = HostMask::host(); uint64_t nonHostMask = HostMask::nonHost(); uint64_t data = 0; // do the minimum that is required // for sending EOI without getting // another interrupt. for host attentions // this is clearing the gpio interrupt // type status register // and for xstp,rec,spcl this is // masking the appropriate bit in // ipoll mask // read the ipoll status register // to determine the interrupt was // caused by host attn or something // else (xstp,rec,spcl) errlHndl_t err = getScom(proc, IPOLL_STATUS_REG, data); if(err) { errlCommit(err, ATTN_COMP_ID); // assume everything is on data = hostMask | nonHostMask; } if(data & hostMask) { // if host attention, clear the ITR macro gpio interrupt // type status register. err = putScom(proc, INTR_TYPE_LCL_ERR_STATUS_AND_REG, 0); if(err) { errlCommit(err, ATTN_COMP_ID); } } if(data & nonHostMask) { // mask local proc xstp,rec and/or special attns if on. // the other thread might be trying to unmask // on the same target. The mutex ensures // neither thread corrupts the register. mutex_lock(&iv_mutex); err = modifyScom(proc, IPOLL::address, data & nonHostMask, SCOM_OR); mutex_unlock(&iv_mutex); if(err) { errlCommit(err, ATTN_COMP_ID); } } }
void ServiceCommon::processAttnPreAck(const TargetHandle_t i_proc) { uint64_t hostMask = HostMask::host(); uint64_t nonHostMask = HostMask::nonHost(); uint64_t data = 0; // do the minimum that is required // for sending EOI without getting // another interrupt. for host attentions // this is clearing the gpio interrupt // type status register // and for xstp,rec,spcl this is // masking the appropriate bit in // ipoll mask // read the ipoll status register // to determine the interrupt was // caused by host attn or something // else (xstp,rec,spcl) errlHndl_t err = getScom(i_proc, IPOLL_STATUS_REG, data); if(err) { errlCommit(err, ATTN_COMP_ID); // assume everything is on data = hostMask | nonHostMask; } if(data & hostMask) { // if host attention, clear the ITR macro gpio interrupt // type status register. err = putScom(i_proc, INTR_TYPE_LCL_ERR_STATUS_AND_REG, 0); if(err) { errlCommit(err, ATTN_COMP_ID); } } if(data & nonHostMask) { // mask local proc xstp,rec and/or special attns if on. // the other thread might be trying to unmask // on the same target. The mutex ensures // neither thread corrupts the register. mutex_lock(&iv_mutex); err = modifyScom(i_proc, IPOLL::address, data & nonHostMask, SCOM_OR); mutex_unlock(&iv_mutex); if(err) { errlCommit(err, ATTN_COMP_ID); } } }
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 ServiceCommon::configureInterrupts( ConfigureMode i_mode) { errlHndl_t err = NULL; 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; } return err; }