1d195b716SZane Shelley
2d195b716SZane Shelley #include <analyzer/plugins/plugin.hpp>
327a17a5bSZane Shelley #include <hei_main.hpp>
4d195b716SZane Shelley #include <util/pdbg.hpp>
5d195b716SZane Shelley #include <util/trace.hpp>
6d195b716SZane Shelley
7d195b716SZane Shelley namespace analyzer
8d195b716SZane Shelley {
9d195b716SZane Shelley
10d195b716SZane Shelley namespace P10
11d195b716SZane Shelley {
12d195b716SZane Shelley
133f363d4aSZane Shelley namespace tod
143f363d4aSZane Shelley {
153f363d4aSZane Shelley
163f363d4aSZane Shelley /** Each chip is connected to two TOD topologies: active and backup. The values
173f363d4aSZane Shelley * are important because some registers and documentation simply refer to them
183f363d4aSZane Shelley * by number instead of name. Also, they can be used as array indexes if
193f363d4aSZane Shelley * needed. */
203f363d4aSZane Shelley enum class Topology
213f363d4aSZane Shelley {
223f363d4aSZane Shelley ACTIVE = 0,
233f363d4aSZane Shelley BACKUP = 1,
243f363d4aSZane Shelley };
253f363d4aSZane Shelley
2627a17a5bSZane Shelley /** Each topology can be configured as either primary or secondary. */
2727a17a5bSZane Shelley enum class Configuration
2827a17a5bSZane Shelley {
2927a17a5bSZane Shelley PRIMARY,
3027a17a5bSZane Shelley SECONDARY,
3127a17a5bSZane Shelley };
3227a17a5bSZane Shelley
333f363d4aSZane Shelley class Data
343f363d4aSZane Shelley {
353f363d4aSZane Shelley public:
363f363d4aSZane Shelley Data() = default;
373f363d4aSZane Shelley ~Data() = default;
383f363d4aSZane Shelley Data(const Data&) = default;
393f363d4aSZane Shelley Data(Data&&) = default;
403f363d4aSZane Shelley Data& operator=(const Data&) = default;
413f363d4aSZane Shelley Data& operator=(Data&&) = default;
423f363d4aSZane Shelley
433f363d4aSZane Shelley private:
443f363d4aSZane Shelley /** The MDMT chips at fault (only one per topology). */
453f363d4aSZane Shelley std::map<Topology, pdbg_target*> iv_mdmtFaultList;
463f363d4aSZane Shelley
473f363d4aSZane Shelley /** All chips with internal path faults. */
483f363d4aSZane Shelley std::map<Topology, std::vector<pdbg_target*>> iv_internalFaultList;
493f363d4aSZane Shelley
503f363d4aSZane Shelley /** The chips sourcing the clocks to non-MDMT chips with faults. */
513f363d4aSZane Shelley std::map<Topology, std::vector<pdbg_target*>> iv_networkFaultList;
523f363d4aSZane Shelley
533f363d4aSZane Shelley public:
543f363d4aSZane Shelley /**
553f363d4aSZane Shelley * @brief Sets this chip as the MDMT at fault for this topology.
563f363d4aSZane Shelley * @param i_topology Target topology.
573f363d4aSZane Shelley * @param i_chipAtFault The chip reporting step check fault.
583f363d4aSZane Shelley */
setMdmtFault(Topology i_topology,pdbg_target * i_chipAtFault)593f363d4aSZane Shelley void setMdmtFault(Topology i_topology, pdbg_target* i_chipAtFault)
603f363d4aSZane Shelley {
613f363d4aSZane Shelley assert(nullptr != i_chipAtFault);
623f363d4aSZane Shelley iv_mdmtFaultList[i_topology] = i_chipAtFault;
633f363d4aSZane Shelley }
643f363d4aSZane Shelley
653f363d4aSZane Shelley /**
663f363d4aSZane Shelley * @param i_topology Target topology.
673f363d4aSZane Shelley * @return The MDMT chip for this topology, if at fault. Otherwise, nullptr.
683f363d4aSZane Shelley */
getMdmtFault(Topology i_topology)693f363d4aSZane Shelley pdbg_target* getMdmtFault(Topology i_topology)
703f363d4aSZane Shelley {
713f363d4aSZane Shelley return iv_mdmtFaultList[i_topology];
723f363d4aSZane Shelley }
733f363d4aSZane Shelley
743f363d4aSZane Shelley /**
753f363d4aSZane Shelley * @brief Indicates the given chip has an internal fault.
763f363d4aSZane Shelley * @param i_topology Target topology.
773f363d4aSZane Shelley * @param i_chipAtFault The chip reporting a step check fault.
783f363d4aSZane Shelley */
setInternalFault(Topology i_topology,pdbg_target * i_chipAtFault)793f363d4aSZane Shelley void setInternalFault(Topology i_topology, pdbg_target* i_chipAtFault)
803f363d4aSZane Shelley {
813f363d4aSZane Shelley assert(nullptr != i_chipAtFault);
823f363d4aSZane Shelley iv_internalFaultList[i_topology].push_back(i_chipAtFault);
833f363d4aSZane Shelley }
843f363d4aSZane Shelley
853f363d4aSZane Shelley /**
863f363d4aSZane Shelley * @param i_topology Target topology.
873f363d4aSZane Shelley * @return The list of all chips with internal faults.
883f363d4aSZane Shelley */
getInteralFaults(Topology i_topology)893f363d4aSZane Shelley const std::vector<pdbg_target*>& getInteralFaults(Topology i_topology)
903f363d4aSZane Shelley {
913f363d4aSZane Shelley return iv_internalFaultList[i_topology];
923f363d4aSZane Shelley }
933f363d4aSZane Shelley
943f363d4aSZane Shelley /**
953f363d4aSZane Shelley * @brief Indicates the given non-MDMT chip has seen a fault in the TOD
963f363d4aSZane Shelley * network.
973f363d4aSZane Shelley * @param i_topology Target topology.
983f363d4aSZane Shelley * @param i_chipSourcingClock The chip sourcing the clock for the chip at
998f07b2e6SZane Shelley * fault.
1008f07b2e6SZane Shelley * @param i_chipAtFault The chip reporting the fault.
1013f363d4aSZane Shelley */
setNetworkFault(Topology i_topology,pdbg_target * i_chipSourcingClock,pdbg_target * i_chipAtFault)1028f07b2e6SZane Shelley void setNetworkFault(Topology i_topology, pdbg_target* i_chipSourcingClock,
1038f07b2e6SZane Shelley pdbg_target* i_chipAtFault)
1043f363d4aSZane Shelley {
1053f363d4aSZane Shelley assert(nullptr != i_chipSourcingClock);
1063f363d4aSZane Shelley iv_networkFaultList[i_topology].push_back(i_chipSourcingClock);
1078f07b2e6SZane Shelley
1088f07b2e6SZane Shelley assert(nullptr != i_chipAtFault);
1098f07b2e6SZane Shelley iv_networkFaultList[i_topology].push_back(i_chipAtFault);
1103f363d4aSZane Shelley }
1113f363d4aSZane Shelley
1123f363d4aSZane Shelley /**
1133f363d4aSZane Shelley * @param i_topology Target topology.
1143f363d4aSZane Shelley * @return The list of all chips sourcing the clocks for the non-MDMT chips
1153f363d4aSZane Shelley * with step check faults.
1163f363d4aSZane Shelley */
getNetworkFaults(Topology i_topology)1173f363d4aSZane Shelley const std::vector<pdbg_target*>& getNetworkFaults(Topology i_topology)
1183f363d4aSZane Shelley {
1193f363d4aSZane Shelley return iv_networkFaultList[i_topology];
1203f363d4aSZane Shelley }
1213f363d4aSZane Shelley };
1223f363d4aSZane Shelley
12327a17a5bSZane Shelley enum class Register
12427a17a5bSZane Shelley {
12527a17a5bSZane Shelley TOD_ERROR = 0x00040030,
12627a17a5bSZane Shelley TOD_PSS_MSS_STATUS = 0x00040008,
12727a17a5bSZane Shelley TOD_PRI_PORT_0_CTRL = 0x00040001,
12827a17a5bSZane Shelley TOD_PRI_PORT_1_CTRL = 0x00040002,
12927a17a5bSZane Shelley TOD_SEC_PORT_0_CTRL = 0x00040003,
13027a17a5bSZane Shelley TOD_SEC_PORT_1_CTRL = 0x00040004,
13127a17a5bSZane Shelley };
13227a17a5bSZane Shelley
readRegister(pdbg_target * i_chip,Register i_addr,libhei::BitStringBuffer & o_val)13327a17a5bSZane Shelley bool readRegister(pdbg_target* i_chip, Register i_addr,
13427a17a5bSZane Shelley libhei::BitStringBuffer& o_val)
13527a17a5bSZane Shelley {
13627a17a5bSZane Shelley assert(64 == o_val.getBitLen());
13727a17a5bSZane Shelley
13827a17a5bSZane Shelley uint64_t scomValue;
13927a17a5bSZane Shelley if (util::pdbg::getScom(i_chip, static_cast<uint64_t>(i_addr), scomValue))
14027a17a5bSZane Shelley {
14127a17a5bSZane Shelley trace::err("Register read failed: addr=0x%08x chip=%s",
14227a17a5bSZane Shelley static_cast<uint64_t>(i_addr), util::pdbg::getPath(i_chip));
14327a17a5bSZane Shelley return true; // SCOM failed
14427a17a5bSZane Shelley }
14527a17a5bSZane Shelley
14627a17a5bSZane Shelley o_val.setFieldRight(0, 64, scomValue);
14727a17a5bSZane Shelley
14827a17a5bSZane Shelley return false; // no failures
14927a17a5bSZane Shelley }
15027a17a5bSZane Shelley
getChipSourcingClock(pdbg_target * i_chipReportingError,unsigned int i_iohsPos)15127a17a5bSZane Shelley pdbg_target* getChipSourcingClock(pdbg_target* i_chipReportingError,
15227a17a5bSZane Shelley unsigned int i_iohsPos)
15327a17a5bSZane Shelley {
15427a17a5bSZane Shelley using namespace util::pdbg;
15527a17a5bSZane Shelley
15627a17a5bSZane Shelley pdbg_target* chipSourcingClock = nullptr;
15727a17a5bSZane Shelley
15827a17a5bSZane Shelley // Given the chip reporting the error and the IOHS position within that
15927a17a5bSZane Shelley // chip, we must get
16027a17a5bSZane Shelley // - The associated IOHS target on this chip.
16127a17a5bSZane Shelley // - Next, the IOHS target on the other side of the bus.
16227a17a5bSZane Shelley // - Finally, the chip containing the IOHS target on the other side of the
16327a17a5bSZane Shelley // bus.
16427a17a5bSZane Shelley
16527a17a5bSZane Shelley auto iohsUnit = getChipUnit(i_chipReportingError, TYPE_IOHS, i_iohsPos);
16627a17a5bSZane Shelley if (nullptr != iohsUnit)
16727a17a5bSZane Shelley {
168*a0c724d3SPatrick Williams auto clockSourceUnit =
169*a0c724d3SPatrick Williams getConnectedTarget(iohsUnit, callout::BusType::SMP_BUS);
17027a17a5bSZane Shelley if (nullptr != clockSourceUnit)
17127a17a5bSZane Shelley {
17227a17a5bSZane Shelley chipSourcingClock = getParentChip(clockSourceUnit);
17327a17a5bSZane Shelley }
17427a17a5bSZane Shelley }
17527a17a5bSZane Shelley
17627a17a5bSZane Shelley return chipSourcingClock;
17727a17a5bSZane Shelley }
17827a17a5bSZane Shelley
1793f363d4aSZane Shelley /**
1803f363d4aSZane Shelley * @brief Collects TOD fault data for each processor chip.
1813f363d4aSZane Shelley */
collectTodFaultData(pdbg_target * i_chip,Data & o_data)18227a17a5bSZane Shelley void collectTodFaultData(pdbg_target* i_chip, Data& o_data)
1833f363d4aSZane Shelley {
18427a17a5bSZane Shelley // TODO: We should use a register cache captured by the isolator so that
18527a17a5bSZane Shelley // this code is using the same values the isolator used. However, at
18627a17a5bSZane Shelley // the moment the isolator does not have a register cache. Instead,
18727a17a5bSZane Shelley // we'll have to manually SCOM the registers we need. Fortunately,
18827a17a5bSZane Shelley // for a checkstop attention the hardware should freeze and the
18927a17a5bSZane Shelley // values will never change. Unfortunately, we don't have that same
19027a17a5bSZane Shelley // guarantee for TIs, but at the time of this writing, all TOD errors
19127a17a5bSZane Shelley // will trigger a checkstop attention away. So the TI case is not as
19227a17a5bSZane Shelley // important.
19327a17a5bSZane Shelley
19427a17a5bSZane Shelley libhei::BitStringBuffer errorReg{64};
19527a17a5bSZane Shelley if (readRegister(i_chip, Register::TOD_ERROR, errorReg))
19627a17a5bSZane Shelley {
19727a17a5bSZane Shelley return; // cannot continue on this chip
19827a17a5bSZane Shelley }
19927a17a5bSZane Shelley
20027a17a5bSZane Shelley libhei::BitStringBuffer statusReg{64};
20127a17a5bSZane Shelley if (readRegister(i_chip, Register::TOD_PSS_MSS_STATUS, statusReg))
20227a17a5bSZane Shelley {
20327a17a5bSZane Shelley return; // cannot continue on this chip
20427a17a5bSZane Shelley }
20527a17a5bSZane Shelley
20627a17a5bSZane Shelley // Determine which topology is configured primary or secondary.
20727a17a5bSZane Shelley std::map<Topology, Configuration> topConfig;
20827a17a5bSZane Shelley
20927a17a5bSZane Shelley if (0 == statusReg.getFieldRight(0, 3))
21027a17a5bSZane Shelley {
21127a17a5bSZane Shelley // TOD_PSS_MSS_STATUS[0:2] == 0b000 means active topology is primary.
21227a17a5bSZane Shelley topConfig[Topology::ACTIVE] = Configuration::PRIMARY;
21327a17a5bSZane Shelley topConfig[Topology::BACKUP] = Configuration::SECONDARY;
21427a17a5bSZane Shelley }
21527a17a5bSZane Shelley else
21627a17a5bSZane Shelley {
21727a17a5bSZane Shelley // TOD_PSS_MSS_STATUS[0:2] == 0b111 means active topology is secondary.
21827a17a5bSZane Shelley topConfig[Topology::ACTIVE] = Configuration::SECONDARY;
21927a17a5bSZane Shelley topConfig[Topology::BACKUP] = Configuration::PRIMARY;
22027a17a5bSZane Shelley }
22127a17a5bSZane Shelley
22227a17a5bSZane Shelley for (const auto top : {Topology::ACTIVE, Topology::BACKUP})
22327a17a5bSZane Shelley {
22427a17a5bSZane Shelley // Bit positions in some registers are dependent on this topology's
22527a17a5bSZane Shelley // configuration.
22627a17a5bSZane Shelley bool isPriTop = (Configuration::PRIMARY == topConfig[top]);
22727a17a5bSZane Shelley
22827a17a5bSZane Shelley // Determine if this is the MDMT chip.
22927a17a5bSZane Shelley bool isMasterTod = statusReg.isBitSet(isPriTop ? 13 : 17);
23027a17a5bSZane Shelley bool isMasterDrawer = statusReg.isBitSet(isPriTop ? 14 : 18);
23127a17a5bSZane Shelley
23227a17a5bSZane Shelley if (isMasterDrawer && isMasterTod)
23327a17a5bSZane Shelley {
23427a17a5bSZane Shelley // The master path selects are sourced from the oscilator reference
23527a17a5bSZane Shelley // clocks. So, we'll need to determine which one was used at the
23627a17a5bSZane Shelley // time of the failure.
237*a0c724d3SPatrick Williams auto masterPathSelect =
238*a0c724d3SPatrick Williams statusReg.getFieldRight(isPriTop ? 12 : 16, 1);
23927a17a5bSZane Shelley
24027a17a5bSZane Shelley // Determine if there is a step check fault for this path select.
24127a17a5bSZane Shelley if (errorReg.isBitSet((0 == masterPathSelect) ? 14 : 15))
24227a17a5bSZane Shelley {
24327a17a5bSZane Shelley trace::inf(
24427a17a5bSZane Shelley "TOD MDMT fault found: top=%u config=%u path=%u chip=%s",
24527a17a5bSZane Shelley static_cast<unsigned int>(top),
24627a17a5bSZane Shelley static_cast<unsigned int>(topConfig[top]), masterPathSelect,
24727a17a5bSZane Shelley util::pdbg::getPath(i_chip));
24827a17a5bSZane Shelley
24927a17a5bSZane Shelley o_data.setMdmtFault(top, i_chip);
25027a17a5bSZane Shelley }
25127a17a5bSZane Shelley }
25227a17a5bSZane Shelley else // not the MDMT on this topology
25327a17a5bSZane Shelley {
25427a17a5bSZane Shelley // The slave path selects are sourced from other processor chips.
25527a17a5bSZane Shelley // So, we'll need to determine which one was used at the time of the
25627a17a5bSZane Shelley // failure.
257*a0c724d3SPatrick Williams auto slavePathSelect =
258*a0c724d3SPatrick Williams statusReg.getFieldRight(isPriTop ? 15 : 19, 1);
25927a17a5bSZane Shelley
26027a17a5bSZane Shelley // Determine if there is a step check fault for this path select.
26127a17a5bSZane Shelley if (errorReg.isBitSet((0 == slavePathSelect) ? 16 : 21))
26227a17a5bSZane Shelley {
26327a17a5bSZane Shelley // Get the IOHS unit position on this chip that is connected to
26427a17a5bSZane Shelley // the clock source chip.
26527a17a5bSZane Shelley auto addr = (0 == slavePathSelect)
26627a17a5bSZane Shelley ? (isPriTop ? Register::TOD_PRI_PORT_0_CTRL
26727a17a5bSZane Shelley : Register::TOD_SEC_PORT_0_CTRL)
26827a17a5bSZane Shelley : (isPriTop ? Register::TOD_PRI_PORT_1_CTRL
26927a17a5bSZane Shelley : Register::TOD_SEC_PORT_1_CTRL);
27027a17a5bSZane Shelley
27127a17a5bSZane Shelley libhei::BitStringBuffer portCtrl{64};
27227a17a5bSZane Shelley if (readRegister(i_chip, addr, portCtrl))
27327a17a5bSZane Shelley {
27427a17a5bSZane Shelley continue; // try the other topology
27527a17a5bSZane Shelley }
27627a17a5bSZane Shelley
27727a17a5bSZane Shelley auto iohsPos = portCtrl.getFieldRight(0, 3);
27827a17a5bSZane Shelley auto chipSourcingClock = getChipSourcingClock(i_chip, iohsPos);
27927a17a5bSZane Shelley
28027a17a5bSZane Shelley if (nullptr != chipSourcingClock)
28127a17a5bSZane Shelley {
28227a17a5bSZane Shelley trace::inf("TOD network fault found: top=%u config=%u "
28327a17a5bSZane Shelley "path=%u chip=%s iohs=%u clockSrc=%s",
28427a17a5bSZane Shelley static_cast<unsigned int>(top),
28527a17a5bSZane Shelley static_cast<unsigned int>(topConfig[top]),
28627a17a5bSZane Shelley slavePathSelect, util::pdbg::getPath(i_chip),
28727a17a5bSZane Shelley iohsPos, util::pdbg::getPath(chipSourcingClock));
28827a17a5bSZane Shelley
2898f07b2e6SZane Shelley o_data.setNetworkFault(top, chipSourcingClock, i_chip);
29027a17a5bSZane Shelley }
29127a17a5bSZane Shelley }
29227a17a5bSZane Shelley }
29327a17a5bSZane Shelley
29427a17a5bSZane Shelley // Check for any internal path errors in the active topology only.
29527a17a5bSZane Shelley if (Topology::ACTIVE == top && errorReg.isBitSet(17))
29627a17a5bSZane Shelley {
29727a17a5bSZane Shelley trace::inf("TOD internal fault found: top=%u config=%u chip=%s",
29827a17a5bSZane Shelley static_cast<unsigned int>(top),
29927a17a5bSZane Shelley static_cast<unsigned int>(topConfig[top]),
30027a17a5bSZane Shelley util::pdbg::getPath(i_chip));
30127a17a5bSZane Shelley
30227a17a5bSZane Shelley o_data.setInternalFault(top, i_chip);
30327a17a5bSZane Shelley }
30427a17a5bSZane Shelley }
3053f363d4aSZane Shelley }
3063f363d4aSZane Shelley
3073f363d4aSZane Shelley } // namespace tod
3083f363d4aSZane Shelley
309d195b716SZane Shelley /**
310d195b716SZane Shelley * @brief Handles TOD step check fault attentions.
311d195b716SZane Shelley */
tod_step_check_fault(unsigned int,const libhei::Chip & i_chip,ServiceData & io_servData)312d195b716SZane Shelley void tod_step_check_fault(unsigned int, const libhei::Chip& i_chip,
313d195b716SZane Shelley ServiceData& io_servData)
314d195b716SZane Shelley {
3153f363d4aSZane Shelley // Query hardware for TOD fault data from all active processors.
3163f363d4aSZane Shelley tod::Data data{};
3173f363d4aSZane Shelley std::vector<pdbg_target*> chipList;
3183f363d4aSZane Shelley util::pdbg::getActiveProcessorChips(chipList);
3193f363d4aSZane Shelley for (const auto& chip : chipList)
3203f363d4aSZane Shelley {
3213f363d4aSZane Shelley tod::collectTodFaultData(chip, data);
3223f363d4aSZane Shelley }
3233f363d4aSZane Shelley
3243f363d4aSZane Shelley // For each topology:
3253f363d4aSZane Shelley // - First, check if the MDMT chip is reporting a fault. If so, it is
3263f363d4aSZane Shelley // likely that any downstream step check faults are due to the fault in
3273f363d4aSZane Shelley // the MDMT.
3283f363d4aSZane Shelley // - If MDMT is not reporting a fault, look for any network path errors
3293f363d4aSZane Shelley // from the non-MDMT chips. In which case, we will want to call out all
3303f363d4aSZane Shelley // of the chips sourcing those step check errors (not the chips reporting
3313f363d4aSZane Shelley // them).
3323f363d4aSZane Shelley // - If no other errors found, callout any chips reporting internal step
3333f363d4aSZane Shelley // check faults.
3343f363d4aSZane Shelley
3353f363d4aSZane Shelley bool calloutsMade = false; // need to keep track for default case.
3363f363d4aSZane Shelley
3373f363d4aSZane Shelley for (const auto top : {tod::Topology::ACTIVE, tod::Topology::BACKUP})
3383f363d4aSZane Shelley {
3393f363d4aSZane Shelley auto mdmtFault = data.getMdmtFault(top);
3403f363d4aSZane Shelley auto internalFaults = data.getInteralFaults(top);
3413f363d4aSZane Shelley auto networkFaults = data.getNetworkFaults(top);
3423f363d4aSZane Shelley
3433f363d4aSZane Shelley if (nullptr != mdmtFault) // MDMT fault
3443f363d4aSZane Shelley {
3453f363d4aSZane Shelley calloutsMade = true;
3463f363d4aSZane Shelley
3473f363d4aSZane Shelley // Callout the TOD clock (guard).
348d195b716SZane Shelley io_servData.calloutClock(callout::ClockType::TOD_CLOCK,
349d195b716SZane Shelley callout::Priority::MED, true);
3503f363d4aSZane Shelley
351026e5a3fSZane Shelley // Callout the MDMT chip (no guard to avoid fatal guard on primary
352026e5a3fSZane Shelley // processor when the error could be anywhere in between).
353026e5a3fSZane Shelley io_servData.calloutTarget(mdmtFault, callout::Priority::MED, false);
3543f363d4aSZane Shelley
3553f363d4aSZane Shelley // Callout everything in between.
3563f363d4aSZane Shelley // TODO: This isn't necessary for now because the clock callout is
3573f363d4aSZane Shelley // the backplane. However, we may need a procedure callout
3583f363d4aSZane Shelley // for future systems.
3593f363d4aSZane Shelley }
3603f363d4aSZane Shelley else if (!networkFaults.empty()) // network path faults
3613f363d4aSZane Shelley {
3623f363d4aSZane Shelley calloutsMade = true;
3633f363d4aSZane Shelley
364026e5a3fSZane Shelley // Callout all chips with network errors (no guard to avoid fatal
365026e5a3fSZane Shelley // guard on primary processor when the error could be anywhere in
366026e5a3fSZane Shelley // between).
3673f363d4aSZane Shelley for (const auto& chip : networkFaults)
3683f363d4aSZane Shelley {
369026e5a3fSZane Shelley io_servData.calloutTarget(chip, callout::Priority::MED, false);
3703f363d4aSZane Shelley }
3713f363d4aSZane Shelley }
3723f363d4aSZane Shelley else if (!internalFaults.empty()) // interal path faults
3733f363d4aSZane Shelley {
3743f363d4aSZane Shelley calloutsMade = true;
3753f363d4aSZane Shelley
376026e5a3fSZane Shelley // Callout all chips with internal errors (guard because error is
377026e5a3fSZane Shelley // isolated to this processor).
3783f363d4aSZane Shelley for (const auto& chip : internalFaults)
3793f363d4aSZane Shelley {
3803f363d4aSZane Shelley io_servData.calloutTarget(chip, callout::Priority::MED, true);
3813f363d4aSZane Shelley }
3823f363d4aSZane Shelley }
3833f363d4aSZane Shelley }
3843f363d4aSZane Shelley
3853f363d4aSZane Shelley // If no callouts are made, default to calling out the chip that reported
3863f363d4aSZane Shelley // the original attention.
3873f363d4aSZane Shelley if (!calloutsMade)
3883f363d4aSZane Shelley {
389d195b716SZane Shelley io_servData.calloutTarget(util::pdbg::getTrgt(i_chip),
3903f363d4aSZane Shelley callout::Priority::MED, true);
3913f363d4aSZane Shelley }
392d195b716SZane Shelley }
393d195b716SZane Shelley
394d195b716SZane Shelley } // namespace P10
395d195b716SZane Shelley
396d195b716SZane Shelley PLUGIN_DEFINE_NS(P10_10, P10, tod_step_check_fault);
397d195b716SZane Shelley PLUGIN_DEFINE_NS(P10_20, P10, tod_step_check_fault);
398d195b716SZane Shelley
399d195b716SZane Shelley } // namespace analyzer
400