1 #include <analyzer/service_data.hpp> 2 3 namespace analyzer 4 { 5 6 //------------------------------------------------------------------------------ 7 8 void ServiceData::calloutTarget(pdbg_target* i_target, 9 const callout::Priority& i_priority, 10 bool i_guard) 11 { 12 // Add the target to the callout list. 13 addTargetCallout(i_target, i_priority, i_guard); 14 15 // Add the callout FFDC. 16 nlohmann::json ffdc; 17 ffdc["Callout Type"] = "Hardware Callout"; 18 ffdc["Target"] = util::pdbg::getPhysDevPath(i_target); 19 ffdc["Priority"] = i_priority.getRegistryString(); 20 ffdc["Guard"] = i_guard; 21 addCalloutFFDC(ffdc); 22 } 23 24 //------------------------------------------------------------------------------ 25 26 void ServiceData::calloutConnected(pdbg_target* i_rxTarget, 27 const callout::BusType& i_busType, 28 const callout::Priority& i_priority, 29 bool i_guard) 30 { 31 // Get the endpoint target for the transfer side of the bus. 32 auto txTarget = util::pdbg::getConnectedTarget(i_rxTarget, i_busType); 33 34 // Callout the TX endpoint. 35 addTargetCallout(txTarget, i_priority, i_guard); 36 37 // Add the callout FFDC. 38 nlohmann::json ffdc; 39 ffdc["Callout Type"] = "Connected Callout"; 40 ffdc["Bus Type"] = i_busType.getString(); 41 ffdc["RX Target"] = util::pdbg::getPhysDevPath(i_rxTarget); 42 ffdc["TX Target"] = util::pdbg::getPhysDevPath(txTarget); 43 ffdc["Priority"] = i_priority.getRegistryString(); 44 ffdc["Guard"] = i_guard; 45 addCalloutFFDC(ffdc); 46 } 47 48 //------------------------------------------------------------------------------ 49 50 void ServiceData::calloutBus(pdbg_target* i_rxTarget, 51 const callout::BusType& i_busType, 52 const callout::Priority& i_priority, bool i_guard) 53 { 54 // Get the endpoint target for the transfer side of the bus. 55 auto txTarget = util::pdbg::getConnectedTarget(i_rxTarget, i_busType); 56 57 // Callout the RX endpoint. 58 addTargetCallout(i_rxTarget, i_priority, i_guard); 59 60 // Callout the TX endpoint. 61 addTargetCallout(txTarget, i_priority, i_guard); 62 63 // Callout everything else in between. 64 // TODO: For P10 (OMI bus and XBUS), the callout is simply the backplane. 65 addBackplaneCallout(i_priority); 66 67 // Add the callout FFDC. 68 nlohmann::json ffdc; 69 ffdc["Callout Type"] = "Bus Callout"; 70 ffdc["Bus Type"] = i_busType.getString(); 71 ffdc["RX Target"] = util::pdbg::getPhysDevPath(i_rxTarget); 72 ffdc["TX Target"] = util::pdbg::getPhysDevPath(txTarget); 73 ffdc["Priority"] = i_priority.getRegistryString(); 74 ffdc["Guard"] = i_guard; 75 addCalloutFFDC(ffdc); 76 } 77 78 //------------------------------------------------------------------------------ 79 80 void ServiceData::calloutClock(const callout::ClockType& i_clockType, 81 const callout::Priority& i_priority, bool) 82 { 83 // Callout the clock target. 84 // TODO: For P10, the callout is simply the backplane. Also, there are no 85 // clock targets in the device tree. So at the moment there is no 86 // guard support for clock targets. 87 addBackplaneCallout(i_priority); 88 89 // Add the callout FFDC. 90 // TODO: Add the target and guard type if guard is ever supported. 91 nlohmann::json ffdc; 92 ffdc["Callout Type"] = "Clock Callout"; 93 ffdc["Clock Type"] = i_clockType.getString(); 94 ffdc["Priority"] = i_priority.getRegistryString(); 95 addCalloutFFDC(ffdc); 96 } 97 98 //------------------------------------------------------------------------------ 99 100 void ServiceData::calloutProcedure(const callout::Procedure& i_procedure, 101 const callout::Priority& i_priority) 102 { 103 // Add the actual callout to the service data. 104 nlohmann::json callout; 105 callout["Procedure"] = i_procedure.getString(); 106 callout["Priority"] = i_priority.getUserDataString(); 107 addCallout(callout); 108 109 // Add the callout FFDC. 110 nlohmann::json ffdc; 111 ffdc["Callout Type"] = "Procedure Callout"; 112 ffdc["Procedure"] = i_procedure.getString(); 113 ffdc["Priority"] = i_priority.getRegistryString(); 114 addCalloutFFDC(ffdc); 115 } 116 117 //------------------------------------------------------------------------------ 118 119 void ServiceData::calloutPart(const callout::PartType& i_part, 120 const callout::Priority& i_priority) 121 { 122 if (callout::PartType::PNOR == i_part) 123 { 124 // The PNOR is on the BMC card. 125 // TODO: Will need to be modified if we ever support systems with more 126 // than one BMC. 127 addTargetCallout(util::pdbg::getTrgt("/bmc0"), i_priority, false); 128 } 129 else 130 { 131 throw std::logic_error("Unsupported part type: " + i_part.getString()); 132 } 133 134 // Add the callout FFDC. 135 nlohmann::json ffdc; 136 ffdc["Callout Type"] = "Part Callout"; 137 ffdc["Part Type"] = i_part.getString(); 138 ffdc["Priority"] = i_priority.getRegistryString(); 139 addCalloutFFDC(ffdc); 140 } 141 142 //------------------------------------------------------------------------------ 143 144 void ServiceData::addCallout(const nlohmann::json& i_callout) 145 { 146 // The new callout is either a hardware callout with a location code or a 147 // procedure callout. 148 149 std::string type{}; 150 if (i_callout.contains("LocationCode")) 151 { 152 type = "LocationCode"; 153 } 154 else if (i_callout.contains("Procedure")) 155 { 156 type = "Procedure"; 157 } 158 else 159 { 160 throw std::logic_error("Unsupported callout: " + i_callout.dump()); 161 } 162 163 // A map to determine the priority order. All of the medium priorities, 164 // including the medium group priorities, are all the same level. 165 static const std::map<std::string, unsigned int> m = { 166 {"H", 3}, {"M", 2}, {"A", 2}, {"B", 2}, {"C", 2}, {"L", 1}, 167 }; 168 169 bool addCallout = true; 170 171 for (auto& c : iv_calloutList) 172 { 173 if (c.contains(type) && (c.at(type) == i_callout.at(type))) 174 { 175 // The new callout already exists. Don't add a new callout. 176 addCallout = false; 177 178 if (m.at(c.at("Priority")) < m.at(i_callout.at("Priority"))) 179 { 180 // The new callout has a higher priority, update it. 181 c["Priority"] = i_callout.at("Priority"); 182 } 183 } 184 } 185 186 if (addCallout) 187 { 188 iv_calloutList.push_back(i_callout); 189 } 190 } 191 192 //------------------------------------------------------------------------------ 193 194 void ServiceData::addTargetCallout(pdbg_target* i_target, 195 const callout::Priority& i_priority, 196 bool i_guard) 197 { 198 nlohmann::json callout; 199 200 callout["LocationCode"] = util::pdbg::getLocationCode(i_target); 201 callout["Priority"] = i_priority.getUserDataString(); 202 callout["Deconfigured"] = false; 203 callout["Guarded"] = false; // default 204 205 // Check if guard info should be added. 206 if (i_guard) 207 { 208 auto guardType = queryGuardPolicy(); 209 210 if (!(callout::GuardType::NONE == guardType)) 211 { 212 callout["Guarded"] = true; 213 callout["EntityPath"] = util::pdbg::getPhysBinPath(i_target); 214 callout["GuardType"] = guardType.getString(); 215 } 216 } 217 218 addCallout(callout); 219 } 220 221 //------------------------------------------------------------------------------ 222 223 void ServiceData::addBackplaneCallout(const callout::Priority& i_priority) 224 { 225 // TODO: There isn't a device tree object for this. So will need to hardcode 226 // the location code for now. In the future, we will need a mechanism 227 // to make this data driven. 228 229 nlohmann::json callout; 230 231 callout["LocationCode"] = "P0"; 232 callout["Priority"] = i_priority.getUserDataString(); 233 callout["Deconfigured"] = false; 234 callout["Guarded"] = false; 235 236 addCallout(callout); 237 } 238 239 //------------------------------------------------------------------------------ 240 241 } // namespace analyzer 242