xref: /openbmc/openpower-hw-diags/analyzer/plugins/p10-tod-plugins.cpp (revision a0c724d3d425032213dbd48247d93cc76d61a331)
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