blob: d835fbe42b7515a2afdcf352311666dbe7986aa0 [file] [log] [blame]
Patrick Williams05e95592021-09-02 09:28:14 -05001#include "pldm.hpp"
2
Rashmica Guptadb38e912023-05-25 10:33:46 +10003#include "libpldm/instance-id.h"
4
Patrick Williams05e95592021-09-02 09:28:14 -05005#include "file.hpp"
6
Patrick Williams05e95592021-09-02 09:28:14 -05007#include <libpldm/entity.h>
Andrew Jeffery97476a12024-06-19 21:07:29 +09308#include <libpldm/oem/ibm/state_set.h>
Patrick Williams05e95592021-09-02 09:28:14 -05009#include <libpldm/platform.h>
10#include <libpldm/state_set.h>
Rashmica Gupta52328cb2023-02-15 10:38:16 +110011#include <libpldm/transport.h>
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -050012#include <libpldm/transport/af-mctp.h>
Rashmica Gupta52328cb2023-02-15 10:38:16 +110013#include <libpldm/transport/mctp-demux.h>
14#include <poll.h>
Patrick Williams05e95592021-09-02 09:28:14 -050015
Chris Cain37abe9b2024-10-31 17:20:31 -050016#include <phosphor-logging/lg2.hpp>
Chris Cainbae4d072022-02-28 09:46:50 -060017#include <sdbusplus/bus.hpp>
18#include <sdeventplus/clock.hpp>
19#include <sdeventplus/exception.hpp>
20#include <sdeventplus/source/io.hpp>
21#include <sdeventplus/source/time.hpp>
22
23#include <algorithm>
Patrick Williams05e95592021-09-02 09:28:14 -050024
25namespace pldm
26{
27
Chris Cainbae4d072022-02-28 09:46:50 -060028using namespace sdeventplus;
29using namespace sdeventplus::source;
30constexpr auto clockId = sdeventplus::ClockId::RealTime;
31using Clock = sdeventplus::Clock<clockId>;
32using Timer = Time<clockId>;
Chris Cain755af102024-02-27 16:09:51 -060033bool Interface::throttleTraces = false;
Chris Cainf0295f52024-09-12 15:41:14 -050034enum pldm_msg_type Interface::msgType = MSG_UNDEFINED;
35open_power::occ::instanceID Interface::resetInstance = 0;
Chris Cainbae4d072022-02-28 09:46:50 -060036
Eddie Jamescbad2192021-10-07 09:39:39 -050037void Interface::fetchSensorInfo(uint16_t stateSetId,
38 SensorToInstance& sensorInstanceMap,
39 SensorOffset& sensorOffset)
Patrick Williams05e95592021-09-02 09:28:14 -050040{
Eddie Jamescbad2192021-10-07 09:39:39 -050041 PdrList pdrs{};
Chris Cainbae4d072022-02-28 09:46:50 -060042 static bool tracedError = false;
Eddie Jamescbad2192021-10-07 09:39:39 -050043
44 auto& bus = open_power::occ::utils::getBus();
45 try
46 {
47 auto method = bus.new_method_call(
48 "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
49 "xyz.openbmc_project.PLDM.PDR", "FindStateSensorPDR");
Chris Cainbae4d072022-02-28 09:46:50 -060050 method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId);
Eddie Jamescbad2192021-10-07 09:39:39 -050051
52 auto responseMsg = bus.call(method);
53 responseMsg.read(pdrs);
54 }
Patrick Williamsaf408082022-07-22 19:26:54 -050055 catch (const sdbusplus::exception_t& e)
Eddie Jamescbad2192021-10-07 09:39:39 -050056 {
Chris Cainbae4d072022-02-28 09:46:50 -060057 if (!tracedError)
58 {
Chris Cain37abe9b2024-10-31 17:20:31 -050059 lg2::error(
60 "fetchSensorInfo: Failed to find stateSetID:{ID} PDR: {ERR}",
61 "ID", stateSetId, "ERR", e.what());
Chris Cainbae4d072022-02-28 09:46:50 -060062 tracedError = true;
63 }
Eddie Jamescbad2192021-10-07 09:39:39 -050064 }
65
66 if (pdrs.empty())
67 {
Chris Cainbae4d072022-02-28 09:46:50 -060068 if (!tracedError)
69 {
Chris Cain37abe9b2024-10-31 17:20:31 -050070 lg2::error("fetchSensorInfo: state sensor PDRs ({ID}) not present",
71 "ID", stateSetId);
Chris Cainbae4d072022-02-28 09:46:50 -060072 tracedError = true;
73 }
Eddie Jamescbad2192021-10-07 09:39:39 -050074 return;
75 }
76
Chris Cainbae4d072022-02-28 09:46:50 -060077 // Found PDR
78 if (tracedError)
79 {
Chris Cain37abe9b2024-10-31 17:20:31 -050080 lg2::info("fetchSensorInfo: found {NUM} PDRs", "NUM", pdrs.size());
Chris Cainbae4d072022-02-28 09:46:50 -060081 tracedError = false;
82 }
83
Patrick Williams05e95592021-09-02 09:28:14 -050084 bool offsetFound = false;
George Liuf3a4a692021-12-28 13:59:51 +080085 auto stateSensorPDR =
Patrick Williams05e95592021-09-02 09:28:14 -050086 reinterpret_cast<const pldm_state_sensor_pdr*>(pdrs.front().data());
George Liuf3a4a692021-12-28 13:59:51 +080087 auto possibleStatesPtr = stateSensorPDR->possible_states;
88 for (auto offset = 0; offset < stateSensorPDR->composite_sensor_count;
89 offset++)
Patrick Williams05e95592021-09-02 09:28:14 -050090 {
91 auto possibleStates =
92 reinterpret_cast<const state_sensor_possible_states*>(
93 possibleStatesPtr);
94
Eddie Jamescbad2192021-10-07 09:39:39 -050095 if (possibleStates->state_set_id == stateSetId)
Patrick Williams05e95592021-09-02 09:28:14 -050096 {
97 sensorOffset = offset;
98 offsetFound = true;
99 break;
100 }
101 possibleStatesPtr += sizeof(possibleStates->state_set_id) +
102 sizeof(possibleStates->possible_states_size) +
103 possibleStates->possible_states_size;
104 }
105
106 if (!offsetFound)
107 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500108 lg2::error("pldm: state sensor PDR not found");
Patrick Williams05e95592021-09-02 09:28:14 -0500109 return;
110 }
111
112 // To order SensorID based on the EntityInstance.
113 // Note that when a proc is on a DCM, the PDRs for these sensors
114 // could have the same instance IDs but different container IDs.
115 std::map<uint32_t, SensorID> entityInstMap{};
116 for (auto& pdr : pdrs)
117 {
118 auto pdrPtr =
119 reinterpret_cast<const pldm_state_sensor_pdr*>(pdr.data());
Chris Cain72d01aa2022-06-14 16:28:03 -0500120 uint32_t key = pdrPtr->sensor_id;
Patrick Williams05e95592021-09-02 09:28:14 -0500121 entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->sensor_id));
122 }
123
124 open_power::occ::instanceID count = start;
Patrick Williamsa49c9872023-05-10 07:50:35 -0500125 for (const auto& pair : entityInstMap)
Patrick Williams05e95592021-09-02 09:28:14 -0500126 {
127 sensorInstanceMap.emplace(pair.second, count);
128 count++;
129 }
130}
131
Patrick Williamsaf408082022-07-22 19:26:54 -0500132void Interface::sensorEvent(sdbusplus::message_t& msg)
Patrick Williams05e95592021-09-02 09:28:14 -0500133{
134 if (!isOCCSensorCacheValid())
135 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500136 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
137 sensorToOCCInstance, OCCSensorOffset);
138 }
Patrick Williams05e95592021-09-02 09:28:14 -0500139
Eddie Jamescbad2192021-10-07 09:39:39 -0500140 if (sensorToSBEInstance.empty())
141 {
142 fetchSensorInfo(PLDM_OEM_IBM_SBE_HRESET_STATE, sensorToSBEInstance,
143 SBESensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -0500144 }
145
Chris Cain72d01aa2022-06-14 16:28:03 -0500146 TerminusID sensorTid{};
Patrick Williams05e95592021-09-02 09:28:14 -0500147 SensorID sensorId{};
148 SensorOffset msgSensorOffset{};
149 EventState eventState{};
150 EventState previousEventState{};
151
Chris Cain72d01aa2022-06-14 16:28:03 -0500152 msg.read(sensorTid, sensorId, msgSensorOffset, eventState,
153 previousEventState);
Patrick Williams05e95592021-09-02 09:28:14 -0500154
Eddie Jamescbad2192021-10-07 09:39:39 -0500155 if (msgSensorOffset == OCCSensorOffset)
Patrick Williams05e95592021-09-02 09:28:14 -0500156 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500157 auto sensorEntry = sensorToOCCInstance.find(sensorId);
Patrick Williams05e95592021-09-02 09:28:14 -0500158
Eddie James432dc482021-11-19 15:29:31 -0600159 if (sensorEntry != sensorToOCCInstance.end())
Eddie Jamescbad2192021-10-07 09:39:39 -0500160 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500161 const uint8_t instance = sensorEntry->second;
Chris Cain755af102024-02-27 16:09:51 -0600162 bool validEvent = true;
Chris Cain7b00cde2023-03-14 15:47:12 -0500163 bool isRunning = false;
Eddie James432dc482021-11-19 15:29:31 -0600164 if (eventState ==
165 static_cast<EventState>(
166 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE))
167 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500168 lg2::info("PLDM: OCC{INST} is RUNNING", "INST", instance);
Chris Cain7b00cde2023-03-14 15:47:12 -0500169 isRunning = true;
Eddie James432dc482021-11-19 15:29:31 -0600170 }
171 else if (eventState ==
172 static_cast<EventState>(
173 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED))
174 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500175 lg2::info("PLDM: OCC{INST} has now STOPPED", "INST", instance);
Eddie James432dc482021-11-19 15:29:31 -0600176 }
Chris Cainbae4d072022-02-28 09:46:50 -0600177 else if (eventState ==
178 static_cast<EventState>(
179 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT))
180 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500181 lg2::error(
182 "PLDM: OCC{INST} has now STOPPED and system is in SAFE MODE",
183 "INST", instance);
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500184
185 // Setting safe mode true
186 safeModeCallBack(true);
Chris Cainbae4d072022-02-28 09:46:50 -0600187 }
188 else
189 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500190 lg2::warning(
191 "PLDM: Unexpected OCC Active sensor state {STATE} for OCC{INST}",
192 "STATE", eventState, "INST", instance);
Chris Cain755af102024-02-27 16:09:51 -0600193 validEvent = false;
Chris Cainbae4d072022-02-28 09:46:50 -0600194 }
Chris Cain755af102024-02-27 16:09:51 -0600195 if (validEvent)
196 {
197 if ((pldmFd > 0) && (instance == pldmResponseOcc))
198 {
199 // Waiting for a response for this OCC, can stop waiting
200 pldmClose();
201 }
Chris Cainf0295f52024-09-12 15:41:14 -0500202 occActiveCallBack(instance, isRunning);
Chris Cain755af102024-02-27 16:09:51 -0600203 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500204 return;
205 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500206 }
Eddie James432dc482021-11-19 15:29:31 -0600207
208 if (msgSensorOffset == SBESensorOffset)
Eddie Jamescbad2192021-10-07 09:39:39 -0500209 {
210 auto sensorEntry = sensorToSBEInstance.find(sensorId);
211
Eddie James432dc482021-11-19 15:29:31 -0600212 if (sensorEntry != sensorToSBEInstance.end())
Eddie Jamescbad2192021-10-07 09:39:39 -0500213 {
Chris Cain12d0b822022-04-22 17:29:18 -0500214 const uint8_t instance = sensorEntry->second;
215 auto match = std::find(outstandingHResets.begin(),
216 outstandingHResets.end(), instance);
217 if (match != outstandingHResets.end())
Eddie James432dc482021-11-19 15:29:31 -0600218 {
Chris Cain12d0b822022-04-22 17:29:18 -0500219 outstandingHResets.erase(match);
220 if (eventState == static_cast<EventState>(SBE_HRESET_NOT_READY))
221 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500222 lg2::error("pldm: HRESET is NOT READY (OCC{INST})", "INST",
223 instance);
Chris Cainf0295f52024-09-12 15:41:14 -0500224 // Stop OCC comm - OCC not usable until it becomes READY
225 occActiveCallBack(instance, false);
226 // Collect SBE FFDC
227 sbeCallBack(instance, false);
228 // Try PM Complex reset
Chris Cain37abe9b2024-10-31 17:20:31 -0500229 lg2::error(
230 "sensorEvent: Requesting OCC reset for OCC{INST}",
231 "INST", instance);
Chris Cainf0295f52024-09-12 15:41:14 -0500232 resetOCC(resetInstance);
Chris Cain12d0b822022-04-22 17:29:18 -0500233 }
234 else if (eventState ==
235 static_cast<EventState>(SBE_HRESET_READY))
236 {
237 sbeCallBack(instance, true);
238 }
239 else if (eventState ==
240 static_cast<EventState>(SBE_HRESET_FAILED))
241 {
242 sbeCallBack(instance, false);
243 }
Chris Cainf0295f52024-09-12 15:41:14 -0500244 else
245 {
246 if (eventState ==
247 static_cast<EventState>(SBE_HRESET_FAILED))
Chris Cain37abe9b2024-10-31 17:20:31 -0500248 lg2::error(
249 "pldm: Unexpected HRESET state {STATE} (OCC{INST})",
250 "STATE", eventState, "INST", instance);
Chris Cainf0295f52024-09-12 15:41:14 -0500251 sbeCallBack(instance, false);
252 }
Eddie James432dc482021-11-19 15:29:31 -0600253 }
Chris Cain12d0b822022-04-22 17:29:18 -0500254 // else request was not from us
Eddie Jamescbad2192021-10-07 09:39:39 -0500255 }
256 }
Patrick Williams05e95592021-09-02 09:28:14 -0500257}
258
Patrick Williamsaf408082022-07-22 19:26:54 -0500259void Interface::hostStateEvent(sdbusplus::message_t& msg)
Chris Cain157467d2022-06-24 11:25:23 -0500260{
261 std::map<std::string, std::variant<std::string>> properties{};
262 std::string interface;
263 msg.read(interface, properties);
264 const auto stateEntry = properties.find("CurrentHostState");
265 if (stateEntry != properties.end())
266 {
267 auto stateEntryValue = stateEntry->second;
268 auto propVal = std::get<std::string>(stateEntryValue);
269 if (propVal == "xyz.openbmc_project.State.Host.HostState.Off")
270 {
271 clearData();
272 }
273 }
274}
275
Chris Cainbae4d072022-02-28 09:46:50 -0600276void Interface::clearData()
277{
Chris Cain72d01aa2022-06-14 16:28:03 -0500278 if (!sensorToOCCInstance.empty())
279 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500280 lg2::info("clearData: Clearing sensorToOCCInstance ({NUM} entries)",
281 "NUM", sensorToOCCInstance.size());
Chris Cain72d01aa2022-06-14 16:28:03 -0500282 for (auto entry : sensorToOCCInstance)
283 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500284 lg2::info("clearData: OCC{INST} / sensorID: {ID}", "INST",
285 entry.second, "ID", lg2::hex, entry.first);
Chris Cainf0295f52024-09-12 15:41:14 -0500286 occActiveCallBack(entry.second, false);
Chris Cain72d01aa2022-06-14 16:28:03 -0500287 }
288 sensorToOCCInstance.clear();
289 }
290 if (!occInstanceToEffecter.empty())
291 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500292 lg2::debug("clearData: Clearing occInstanceToEffecter ({NUM} entries)",
293 "NUM", occInstanceToEffecter.size());
Chris Cain72d01aa2022-06-14 16:28:03 -0500294 occInstanceToEffecter.clear();
295 }
296 if (!sensorToSBEInstance.empty())
297 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500298 lg2::debug("clearData: Clearing sensorToSBEInstance ({NUM} entries)",
299 "NUM", sensorToSBEInstance.size());
Chris Cain72d01aa2022-06-14 16:28:03 -0500300 sensorToSBEInstance.clear();
301 }
302 if (!sbeInstanceToEffecter.empty())
303 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500304 lg2::debug("clearData: Clearing sbeInstanceToEffecter ({NUM} entries)",
305 "NUM", sbeInstanceToEffecter.size());
Chris Cain72d01aa2022-06-14 16:28:03 -0500306 sbeInstanceToEffecter.clear();
307 }
Chris Cainbae4d072022-02-28 09:46:50 -0600308}
309
Patrick Williamsd7542c82024-08-16 15:20:28 -0400310void Interface::fetchEffecterInfo(
311 uint16_t stateSetId, InstanceToEffecter& instanceToEffecterMap,
312 CompositeEffecterCount& effecterCount, uint8_t& stateIdPos)
Patrick Williams05e95592021-09-02 09:28:14 -0500313{
Eddie Jamescbad2192021-10-07 09:39:39 -0500314 PdrList pdrs{};
315
316 auto& bus = open_power::occ::utils::getBus();
317 try
318 {
319 auto method = bus.new_method_call(
320 "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
321 "xyz.openbmc_project.PLDM.PDR", "FindStateEffecterPDR");
Chris Cainbae4d072022-02-28 09:46:50 -0600322 method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId);
Eddie Jamescbad2192021-10-07 09:39:39 -0500323
324 auto responseMsg = bus.call(method);
325 responseMsg.read(pdrs);
326 }
Patrick Williamsaf408082022-07-22 19:26:54 -0500327 catch (const sdbusplus::exception_t& e)
Eddie Jamescbad2192021-10-07 09:39:39 -0500328 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500329 lg2::error("pldm: Failed to fetch the state effecter PDRs: {ERR}",
330 "ERR", e.what());
Eddie Jamescbad2192021-10-07 09:39:39 -0500331 }
332
333 if (!pdrs.size())
334 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500335 lg2::error("pldm: state effecter PDRs not present");
Eddie Jamescbad2192021-10-07 09:39:39 -0500336 return;
337 }
338
Patrick Williams05e95592021-09-02 09:28:14 -0500339 bool offsetFound = false;
George Liuf3a4a692021-12-28 13:59:51 +0800340 auto stateEffecterPDR =
Patrick Williams05e95592021-09-02 09:28:14 -0500341 reinterpret_cast<const pldm_state_effecter_pdr*>(pdrs.front().data());
George Liuf3a4a692021-12-28 13:59:51 +0800342 auto possibleStatesPtr = stateEffecterPDR->possible_states;
343 for (auto offset = 0; offset < stateEffecterPDR->composite_effecter_count;
344 offset++)
Patrick Williams05e95592021-09-02 09:28:14 -0500345 {
346 auto possibleStates =
347 reinterpret_cast<const state_effecter_possible_states*>(
348 possibleStatesPtr);
349
Eddie Jamescbad2192021-10-07 09:39:39 -0500350 if (possibleStates->state_set_id == stateSetId)
Patrick Williams05e95592021-09-02 09:28:14 -0500351 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500352 stateIdPos = offset;
George Liuf3a4a692021-12-28 13:59:51 +0800353 effecterCount = stateEffecterPDR->composite_effecter_count;
Patrick Williams05e95592021-09-02 09:28:14 -0500354 offsetFound = true;
355 break;
356 }
357 possibleStatesPtr += sizeof(possibleStates->state_set_id) +
358 sizeof(possibleStates->possible_states_size) +
359 possibleStates->possible_states_size;
360 }
361
362 if (!offsetFound)
363 {
364 return;
365 }
366
Chris Cain0f516522022-02-07 14:48:28 -0600367 std::map<uint32_t, EffecterID> entityInstMap{};
Patrick Williams05e95592021-09-02 09:28:14 -0500368 for (auto& pdr : pdrs)
369 {
370 auto pdrPtr =
371 reinterpret_cast<const pldm_state_effecter_pdr*>(pdr.data());
Chris Cain72d01aa2022-06-14 16:28:03 -0500372 uint32_t key = pdrPtr->effecter_id;
Patrick Williams05e95592021-09-02 09:28:14 -0500373 entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->effecter_id));
374 }
375
376 open_power::occ::instanceID position = start;
Patrick Williamsa49c9872023-05-10 07:50:35 -0500377 for (const auto& pair : entityInstMap)
Patrick Williams05e95592021-09-02 09:28:14 -0500378 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500379 instanceToEffecterMap.emplace(position, pair.second);
Patrick Williams05e95592021-09-02 09:28:14 -0500380 position++;
381 }
382}
383
Patrick Williamsd7542c82024-08-16 15:20:28 -0400384std::vector<uint8_t> Interface::prepareSetEffecterReq(
385 EffecterID effecterId, CompositeEffecterCount effecterCount,
386 uint8_t stateIdPos, uint8_t stateSetValue)
Patrick Williams05e95592021-09-02 09:28:14 -0500387{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100388 if (!getPldmInstanceId())
Chris Cain8b508bf2022-05-26 14:01:31 -0500389 {
390 return std::vector<uint8_t>();
391 }
392
Patrick Williams05e95592021-09-02 09:28:14 -0500393 std::vector<uint8_t> request(
394 sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(effecterCount) +
395 (effecterCount * sizeof(set_effecter_state_field)));
396 auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
397 std::vector<set_effecter_state_field> stateField;
398
399 for (uint8_t effecterPos = 0; effecterPos < effecterCount; effecterPos++)
400 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500401 if (effecterPos == stateIdPos)
Patrick Williams05e95592021-09-02 09:28:14 -0500402 {
Eddie Jamescbad2192021-10-07 09:39:39 -0500403 stateField.emplace_back(
404 set_effecter_state_field{PLDM_REQUEST_SET, stateSetValue});
Patrick Williams05e95592021-09-02 09:28:14 -0500405 }
406 else
407 {
408 stateField.emplace_back(
409 set_effecter_state_field{PLDM_NO_CHANGE, 0});
410 }
411 }
412 auto rc = encode_set_state_effecter_states_req(
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100413 pldmInstanceID.value(), effecterId, effecterCount, stateField.data(),
Chris Cain8b508bf2022-05-26 14:01:31 -0500414 requestMsg);
Patrick Williams05e95592021-09-02 09:28:14 -0500415 if (rc != PLDM_SUCCESS)
416 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500417 lg2::error("encode set effecter states request returned error rc={RC}",
418 "RC", rc);
Patrick Williams05e95592021-09-02 09:28:14 -0500419 request.clear();
420 }
421 return request;
422}
423
424void Interface::resetOCC(open_power::occ::instanceID occInstanceId)
425{
Chris Cainbae4d072022-02-28 09:46:50 -0600426 if (open_power::occ::utils::isHostRunning())
Patrick Williams05e95592021-09-02 09:28:14 -0500427 {
Chris Cainbae4d072022-02-28 09:46:50 -0600428 if (!isPDREffecterCacheValid())
429 {
430 fetchEffecterInfo(PLDM_STATE_SET_BOOT_RESTART_CAUSE,
431 occInstanceToEffecter, OCCEffecterCount,
432 bootRestartPosition);
433 }
Patrick Williams05e95592021-09-02 09:28:14 -0500434
Chris Cainbae4d072022-02-28 09:46:50 -0600435 // Find the matching effecter for the OCC instance
436 auto effecterEntry = occInstanceToEffecter.find(occInstanceId);
437 if (effecterEntry == occInstanceToEffecter.end())
438 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500439 lg2::error(
440 "pldm: Failed to find a matching effecter for OCC instance {INST}",
441 "INST", occInstanceId);
Chris Cainbae4d072022-02-28 09:46:50 -0600442
443 return;
444 }
445
Chris Cainbae4d072022-02-28 09:46:50 -0600446 // Prepare the SetStateEffecterStates request to reset the OCC
447 auto request = prepareSetEffecterReq(
Chris Cain8b508bf2022-05-26 14:01:31 -0500448 effecterEntry->second, OCCEffecterCount, bootRestartPosition,
449 PLDM_STATE_SET_BOOT_RESTART_CAUSE_WARM_RESET);
Chris Cainbae4d072022-02-28 09:46:50 -0600450
451 if (request.empty())
452 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500453 lg2::error("pldm: SetStateEffecterStates OCC reset request empty");
Chris Cainbae4d072022-02-28 09:46:50 -0600454 return;
455 }
456
Chris Cainf0295f52024-09-12 15:41:14 -0500457 // Send request to reset the OCCs/PM Complex (and wait for response)
458 msgType = MSG_OCC_RESET;
459 resetInstance = occInstanceId;
460 sendPldm(request, occInstanceId, true);
Chris Cainbae4d072022-02-28 09:46:50 -0600461 }
462 else
Patrick Williams05e95592021-09-02 09:28:14 -0500463 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500464 lg2::error("resetOCC: HOST is not running (OCC{INST})", "INST",
465 occInstanceId);
Chris Cainbae4d072022-02-28 09:46:50 -0600466 clearData();
Patrick Williams05e95592021-09-02 09:28:14 -0500467 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500468}
469
470void Interface::sendHRESET(open_power::occ::instanceID sbeInstanceId)
471{
Chris Cainbae4d072022-02-28 09:46:50 -0600472 if (open_power::occ::utils::isHostRunning())
Eddie Jamescbad2192021-10-07 09:39:39 -0500473 {
Chris Cainbae4d072022-02-28 09:46:50 -0600474 if (sbeInstanceToEffecter.empty())
475 {
476 fetchEffecterInfo(PLDM_OEM_IBM_SBE_MAINTENANCE_STATE,
477 sbeInstanceToEffecter, SBEEffecterCount,
478 sbeMaintenanceStatePosition);
479 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500480
Chris Cainbae4d072022-02-28 09:46:50 -0600481 auto effecterEntry = sbeInstanceToEffecter.find(sbeInstanceId);
482 if (effecterEntry == sbeInstanceToEffecter.end())
483 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500484 lg2::error(
485 "pldm: Failed to find a matching effecter for SBE instance {INST}",
486 "INST", sbeInstanceId);
Chris Cainbae4d072022-02-28 09:46:50 -0600487 return;
488 }
489
Chris Cainbae4d072022-02-28 09:46:50 -0600490 // Prepare the SetStateEffecterStates request to HRESET the SBE
491 auto request = prepareSetEffecterReq(
Chris Cain8b508bf2022-05-26 14:01:31 -0500492 effecterEntry->second, SBEEffecterCount,
Chris Cainbae4d072022-02-28 09:46:50 -0600493 sbeMaintenanceStatePosition, SBE_RETRY_REQUIRED);
494
495 if (request.empty())
496 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500497 lg2::error("pldm: SetStateEffecterStates HRESET request empty");
Chris Cainbae4d072022-02-28 09:46:50 -0600498 return;
499 }
500
Chris Cainf0295f52024-09-12 15:41:14 -0500501 // Send request to issue HRESET of SBE (and wait for response)
502 msgType = MSG_HRESET;
503 resetInstance = sbeInstanceId;
504 sendPldm(request, sbeInstanceId, true);
Chris Cain12d0b822022-04-22 17:29:18 -0500505 outstandingHResets.insert(sbeInstanceId);
Chris Cainbae4d072022-02-28 09:46:50 -0600506 }
507 else
Eddie Jamescbad2192021-10-07 09:39:39 -0500508 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500509 lg2::error("sendHRESET: HOST is not running (OCC{INST})", "INST",
510 sbeInstanceId);
Chris Cainbae4d072022-02-28 09:46:50 -0600511 clearData();
Eddie Jamescbad2192021-10-07 09:39:39 -0500512 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500513}
514
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100515bool Interface::getPldmInstanceId()
Eddie Jamescbad2192021-10-07 09:39:39 -0500516{
Rashmica Guptadb38e912023-05-25 10:33:46 +1000517 pldm_instance_id_t id;
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100518 if (!pldmInstanceID)
Patrick Williams05e95592021-09-02 09:28:14 -0500519 {
Chris Cain8b508bf2022-05-26 14:01:31 -0500520 // Request new instance ID
Rashmica Guptadb38e912023-05-25 10:33:46 +1000521 int rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
522 if (rc == -EAGAIN)
Chris Cain8b508bf2022-05-26 14:01:31 -0500523 {
Rashmica Guptadb38e912023-05-25 10:33:46 +1000524 std::this_thread::sleep_for(std::chrono::milliseconds(100));
525 rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
Chris Cain8b508bf2022-05-26 14:01:31 -0500526 }
Rashmica Guptadb38e912023-05-25 10:33:46 +1000527
528 if (rc)
Chris Cain8b508bf2022-05-26 14:01:31 -0500529 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500530 lg2::error(
531 "getPldmInstanceId: Failed to alloc ID for TID {TID}. RC{RC}",
532 "TID", tid, "RC", rc);
Chris Cain8b508bf2022-05-26 14:01:31 -0500533 return false;
534 }
Rashmica Guptadb38e912023-05-25 10:33:46 +1000535 pldmInstanceID.emplace(id);
536 if (!throttleTraces)
537 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500538 lg2::info("got id {ID} and set PldmInstanceId to {INST}", "ID", id,
539 "INST", pldmInstanceID.value());
Rashmica Guptadb38e912023-05-25 10:33:46 +1000540 }
Patrick Williams05e95592021-09-02 09:28:14 -0500541 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500542 return true;
543}
Patrick Williams05e95592021-09-02 09:28:14 -0500544
Rashmica Guptadb38e912023-05-25 10:33:46 +1000545void Interface::freePldmInstanceId()
546{
547 if (pldmInstanceID)
548 {
549 int rc = pldm_instance_id_free(pldmInstanceIdDb, tid,
550 pldmInstanceID.value());
551 if (rc)
552 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500553 lg2::error(
554 "freePldmInstanceId: Failed to free ID {ID} for TID {TID}. RC{RC}",
555 "ID", pldmInstanceID.value(), "TID", tid, "RC", rc);
Rashmica Guptadb38e912023-05-25 10:33:46 +1000556 return;
557 }
558 if (!throttleTraces)
559 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500560 lg2::info("Freed PLDM instance ID {ID}", "ID",
561 pldmInstanceID.value());
Rashmica Guptadb38e912023-05-25 10:33:46 +1000562 }
563 pldmInstanceID = std::nullopt;
564 }
565}
566
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500567[[maybe_unused]] int Interface::openMctpDemuxTransport()
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100568{
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500569 impl.mctpDemux = nullptr;
570 int rc = pldm_transport_mctp_demux_init(&impl.mctpDemux);
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100571 if (rc)
572 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500573 lg2::error(
574 "openMctpDemuxTransport: Failed to init MCTP demux transport, errno={ERR}/{STR}",
575 "ERR", rc, "STR", strerror(rc));
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100576 return -1;
577 }
578
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500579 if (pldm_transport_mctp_demux_map_tid(impl.mctpDemux, mctpEid, mctpEid))
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100580 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500581 lg2::error(
582 "openMctpDemuxTransport: Failed to setup tid to eid mapping, errno={ERR}/{STR}",
583 "ERR", errno, "STR", strerror(errno));
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100584 pldmClose();
585 return -1;
586 }
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500587 pldmTransport = pldm_transport_mctp_demux_core(impl.mctpDemux);
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100588
589 struct pollfd pollfd;
590 if (pldm_transport_mctp_demux_init_pollfd(pldmTransport, &pollfd))
591 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500592 lg2::error(
593 "openMctpDemuxTransport: Failed to get pollfd , errno={ERR}/{STR}",
594 "ERR", errno, "STR", strerror(errno));
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100595 pldmClose();
596 return -1;
597 }
598 pldmFd = pollfd.fd;
599 if (!throttleTraces)
600 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500601 lg2::info("openMctpDemuxTransport: pldmFd has fd={FD}", "FD", pldmFd);
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100602 }
603 return 0;
604}
605
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500606[[maybe_unused]] int Interface::openAfMctpTransport()
607{
608 impl.afMctp = nullptr;
609 int rc = pldm_transport_af_mctp_init(&impl.afMctp);
610 if (rc)
611 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500612 lg2::error(
613 "openAfMctpTransport: Failed to init af MCTP transport, errno={ERR}/{STR}",
614 "ERR", rc, "STR", strerror(rc));
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500615 return -1;
616 }
617
618 if (pldm_transport_af_mctp_map_tid(impl.afMctp, mctpEid, mctpEid))
619 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500620 lg2::error(
621 "openAfMctpTransport: Failed to setup tid to eid mapping, errno={ERR}/{STR}",
622 "ERR", errno, "STR", strerror(errno));
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500623 pldmClose();
624 return -1;
625 }
626 pldmTransport = pldm_transport_af_mctp_core(impl.afMctp);
627
628 struct pollfd pollfd;
629 if (pldm_transport_af_mctp_init_pollfd(pldmTransport, &pollfd))
630 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500631 lg2::error(
632 "openAfMctpTransport: Failed to get pollfd , errno={ERR}/{STR}",
633 "ERR", errno, "STR", strerror(errno));
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500634 pldmClose();
635 return -1;
636 }
637 pldmFd = pollfd.fd;
638 if (!throttleTraces)
639 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500640 lg2::info("openAfMctpTransport: pldmFd has fd={FD}", "FD", pldmFd);
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500641 }
642 return 0;
643}
644
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100645int Interface::pldmOpen()
646{
647 if (pldmTransport)
648 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500649 lg2::error("pldmOpen: pldmTransport already setup!, errno={ERR}/{STR}",
650 "ERR", errno, "STR", strerror(errno));
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100651 return -1;
652 }
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500653#if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX)
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100654 return openMctpDemuxTransport();
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500655#elif defined(PLDM_TRANSPORT_WITH_AF_MCTP)
656 return openAfMctpTransport();
657#else
Chris Cain37abe9b2024-10-31 17:20:31 -0500658 lg2::error("pldmOpen: Undefined pldmTransport!, errno={ERR}/{STR}", "ERR",
659 errno, "STR", strerror(errno));
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500660 return -1;
661#endif
662
663 return 0;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100664}
665
Chris Cainbae4d072022-02-28 09:46:50 -0600666void Interface::sendPldm(const std::vector<uint8_t>& request,
667 const uint8_t instance, const bool rspExpected)
Eddie Jamescbad2192021-10-07 09:39:39 -0500668{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100669 if (!pldmInstanceID)
Chris Cain8b508bf2022-05-26 14:01:31 -0500670 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500671 lg2::error("sendPldm: No PLDM Instance ID found!");
Chris Cain8b508bf2022-05-26 14:01:31 -0500672 return;
673 }
674
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100675 auto rc = pldmOpen();
676 if (rc)
Patrick Williams05e95592021-09-02 09:28:14 -0500677 {
Eddie James88811ad2024-08-27 13:39:05 -0500678 if (!throttleTraces)
679 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500680 lg2::error("sendPldm: pldmOpen failed rc={RC}", "RC", rc);
Eddie James88811ad2024-08-27 13:39:05 -0500681 }
Rashmica Guptadb38e912023-05-25 10:33:46 +1000682 freePldmInstanceId();
Patrick Williams05e95592021-09-02 09:28:14 -0500683 return;
684 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500685
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100686 pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEid);
Patrick Williams05e95592021-09-02 09:28:14 -0500687 // Send the PLDM request message to HBRT
Chris Cainbae4d072022-02-28 09:46:50 -0600688 if (rspExpected)
Patrick Williams05e95592021-09-02 09:28:14 -0500689 {
Chris Cainbae4d072022-02-28 09:46:50 -0600690 // Register callback when response is available
691 registerPldmRspCallback();
692
Chris Cainf0295f52024-09-12 15:41:14 -0500693 using namespace std::literals::chrono_literals;
694 std::chrono::duration timeout = 8s;
695 if ((msgType == MSG_OCC_RESET) || (msgType == MSG_HRESET))
696 {
697 timeout = 30s;
698 }
699
Chris Cainbae4d072022-02-28 09:46:50 -0600700 // Send PLDM request
Chris Cain755af102024-02-27 16:09:51 -0600701 if (!throttleTraces)
702 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500703 lg2::info("sendPldm: calling pldm_transport_send_msg(OCC{INST}, "
704 "instance:{ID}, {LEN} bytes, timeout {TO})",
705 "INST", instance, "ID", pldmInstanceID.value(), "LEN",
706 request.size(), "TO", timeout.count());
Chris Cain755af102024-02-27 16:09:51 -0600707 }
Chris Cainbae4d072022-02-28 09:46:50 -0600708 pldmResponseReceived = false;
709 pldmResponseTimeout = false;
710 pldmResponseOcc = instance;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100711 auto pldmRc = pldm_transport_send_msg(pldmTransport, pldmTID,
712 request.data(), request.size());
Chris Cainbae4d072022-02-28 09:46:50 -0600713 auto sendErrno = errno;
714 if (pldmRc != PLDM_REQUESTER_SUCCESS)
715 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500716 lg2::error(
717 "sendPldm: pldm_transport_send_msg failed with rc={RC} and errno={ERR}/{STR}",
718 "RC",
719 static_cast<std::underlying_type_t<pldm_requester_error_codes>>(
720 pldmRc),
721 "ERR", sendErrno, "STR", strerror(sendErrno));
Chris Cainbae4d072022-02-28 09:46:50 -0600722 pldmClose();
723 return;
724 }
725
726 // start timer waiting for the response
Chris Cainf0295f52024-09-12 15:41:14 -0500727 pldmRspTimer.restartOnce(timeout);
Chris Cainbae4d072022-02-28 09:46:50 -0600728
729 // Wait for response/timeout
730 }
731 else // not expecting the response
732 {
Chris Cain755af102024-02-27 16:09:51 -0600733 if (!throttleTraces)
734 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500735 lg2::info(
736 "sendPldm: calling pldm_transport_send_msg(mctpID:{ID}, fd:{FD}, "
737 "{LEN} bytes) for OCC{INST}",
738 "ID", mctpEid, "FD", pldmFd, "LEN", request.size(), "INST",
739 instance);
Chris Cain755af102024-02-27 16:09:51 -0600740 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100741 auto rc = pldm_transport_send_msg(pldmTransport, pldmTID,
742 request.data(), request.size());
Chris Cainbae4d072022-02-28 09:46:50 -0600743 auto sendErrno = errno;
Chris Caind1b68262022-02-28 09:56:50 -0600744 if (rc)
745 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500746 lg2::error(
747 "sendPldm: pldm_transport_send_msg(mctpID:{ID}, fd:{FD}, {LEN} bytes) "
748 "failed with rc={RC} and errno={ERR}/{STR}",
749 "ID", mctpEid, "FD", pldmFd, "LEN", request.size(), "RC",
750 static_cast<std::underlying_type_t<pldm_requester_error_codes>>(
751 rc),
752 "ERR", sendErrno, "STR", strerror(sendErrno));
Chris Caind1b68262022-02-28 09:56:50 -0600753 }
Chris Cainbae4d072022-02-28 09:46:50 -0600754 pldmClose();
755 }
756}
Patrick Williams05e95592021-09-02 09:28:14 -0500757
Chris Cainbae4d072022-02-28 09:46:50 -0600758// Attaches the FD to event loop and registers the callback handler
759void Interface::registerPldmRspCallback()
760{
761 decltype(eventSource.get()) sourcePtr = nullptr;
Chris Cainf0295f52024-09-12 15:41:14 -0500762 int rc = 0;
763 if ((msgType == MSG_OCC_RESET) || (msgType == MSG_HRESET))
764 {
765 rc = sd_event_add_io(event.get(), &sourcePtr, pldmFd, EPOLLIN,
766 pldmResetCallback, this);
767 }
768 else
769 {
770 rc = sd_event_add_io(event.get(), &sourcePtr, pldmFd, EPOLLIN,
771 pldmRspCallback, this);
772 }
Chris Cainbae4d072022-02-28 09:46:50 -0600773 if (rc < 0)
774 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500775 lg2::error(
776 "registerPldmRspCallback: sd_event_add_io: Error({ERR})={STR} : fd={FD} (msgType={MSG})",
777 "ERR", rc, "STR", strerror(-rc), "FD", pldmFd, "MSG", msgType);
Chris Caind1b68262022-02-28 09:56:50 -0600778 }
779 else
Patrick Williams05e95592021-09-02 09:28:14 -0500780 {
Chris Cainbae4d072022-02-28 09:46:50 -0600781 // puts sourcePtr in the event source.
782 eventSource.reset(sourcePtr);
783 }
784}
785
786// Add a timer to the event loop, default 30s.
787void Interface::pldmRspExpired()
788{
789 if (!pldmResponseReceived)
790 {
Chris Cain755af102024-02-27 16:09:51 -0600791 if (!throttleTraces)
792 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500793 lg2::warning(
794 "pldmRspExpired: timerCallback - timeout waiting for pldm "
795 "response to msg:{MSG} for OCC{INST}",
796 "MSG", msgType, "INST", pldmResponseOcc);
Chris Cain755af102024-02-27 16:09:51 -0600797 }
Chris Cainbae4d072022-02-28 09:46:50 -0600798 pldmResponseTimeout = true;
799 if (pldmFd)
800 {
801 pldmClose();
802 }
Chris Cainf0295f52024-09-12 15:41:14 -0500803 if (msgType == MSG_OCC_RESET)
804 {
805 // reset not acked, try again
Chris Cain37abe9b2024-10-31 17:20:31 -0500806 lg2::error("pldmRspExpired: retrying reset request for OCC{INST}",
807 "INST", pldmResponseOcc);
Chris Cainf0295f52024-09-12 15:41:14 -0500808 resetOCC(pldmResponseOcc);
809 }
Chris Cainbae4d072022-02-28 09:46:50 -0600810 }
811 return;
812};
813
814void Interface::pldmClose()
815{
Rashmica Guptadb38e912023-05-25 10:33:46 +1000816 freePldmInstanceId();
Chris Cainbae4d072022-02-28 09:46:50 -0600817 if (pldmRspTimer.isEnabled())
818 {
819 // stop PLDM response timer
820 pldmRspTimer.setEnabled(false);
821 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100822
Lakshmi Yadlapati6213f192024-07-01 11:50:09 -0500823#if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX)
824 pldm_transport_mctp_demux_destroy(impl.mctpDemux);
825 impl.mctpDemux = NULL;
826#elif defined(PLDM_TRANSPORT_WITH_AF_MCTP)
827 pldm_transport_af_mctp_destroy(impl.afMctp);
828 impl.afMctp = NULL;
829#endif
Chris Cainbae4d072022-02-28 09:46:50 -0600830 pldmFd = -1;
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100831 pldmTransport = NULL;
Chris Cainbae4d072022-02-28 09:46:50 -0600832 eventSource.reset();
833}
834
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100835int Interface::pldmRspCallback(sd_event_source* /*es*/,
836 __attribute__((unused)) int fd, uint32_t revents,
837 void* userData)
Chris Cainbae4d072022-02-28 09:46:50 -0600838{
839 if (!(revents & EPOLLIN))
840 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500841 lg2::info("pldmRspCallback - revents={NUM}", "NUM", lg2::hex, revents);
Chris Cainbae4d072022-02-28 09:46:50 -0600842 return -1;
843 }
844
845 auto pldmIface = static_cast<Interface*>(userData);
846
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100847 if (!pldmIface->pldmInstanceID)
Chris Cain8b508bf2022-05-26 14:01:31 -0500848 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500849 lg2::error("pldmRspCallback: No outstanding PLDM Instance ID found");
Chris Cain8b508bf2022-05-26 14:01:31 -0500850 return -1;
851 }
852
Chris Cainbae4d072022-02-28 09:46:50 -0600853 uint8_t* responseMsg = nullptr;
854 size_t responseMsgSize{};
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100855 pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEid);
Chris Cainbae4d072022-02-28 09:46:50 -0600856
Chris Cain755af102024-02-27 16:09:51 -0600857 if (!throttleTraces)
858 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500859 lg2::info(
860 "pldmRspCallback: calling pldm_transport_recv_msg() instance:{INST}",
861 "INST", pldmIface->pldmInstanceID.value());
Chris Cain755af102024-02-27 16:09:51 -0600862 }
Rashmica Gupta52328cb2023-02-15 10:38:16 +1100863 auto rc = pldm_transport_recv_msg(pldmIface->pldmTransport, &pldmTID,
864 (void**)&responseMsg, &responseMsgSize);
Chris Cainbae4d072022-02-28 09:46:50 -0600865 int lastErrno = errno;
866 if (rc)
867 {
Chris Cain755af102024-02-27 16:09:51 -0600868 if (!throttleTraces)
869 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500870 lg2::error(
871 "pldmRspCallback: pldm_transport_recv_msg failed with rc={RC}, errno={ERR}/{STR}",
872 "RC",
873 static_cast<std::underlying_type_t<pldm_requester_error_codes>>(
874 rc),
875 "ERR", lastErrno, "STR", strerror(lastErrno));
Chris Cain755af102024-02-27 16:09:51 -0600876 }
Chris Cainbae4d072022-02-28 09:46:50 -0600877 return -1;
878 }
Chris Cain8b508bf2022-05-26 14:01:31 -0500879
880 // We got the response for the PLDM request msg that was sent
Chris Cain755af102024-02-27 16:09:51 -0600881 if (!throttleTraces)
882 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500883 lg2::info(
884 "pldmRspCallback: pldm_transport_recv_msg() rsp was {LEN} bytes",
885 "LEN", responseMsgSize);
Chris Cain755af102024-02-27 16:09:51 -0600886 }
Chris Cainbae4d072022-02-28 09:46:50 -0600887
888 if (pldmIface->pldmRspTimer.isEnabled())
889 {
890 // stop PLDM response timer
891 pldmIface->pldmRspTimer.setEnabled(false);
892 }
893
Chris Cain8b508bf2022-05-26 14:01:31 -0500894 // instance ID should be freed
Rashmica Guptaaeba51c2023-02-17 12:30:46 +1100895 pldmIface->pldmInstanceID = std::nullopt;
Chris Cain8b508bf2022-05-26 14:01:31 -0500896
Chris Cainbae4d072022-02-28 09:46:50 -0600897 // Set pointer to autodelete
Patrick Williamsd7542c82024-08-16 15:20:28 -0400898 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{
899 responseMsg, std::free};
Chris Cainbae4d072022-02-28 09:46:50 -0600900
Chris Cainbae4d072022-02-28 09:46:50 -0600901 auto response = reinterpret_cast<pldm_msg*>(responseMsgPtr.get());
902 if (response->payload[0] != PLDM_SUCCESS)
903 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500904 lg2::error("pldmRspCallback: payload[0] was not success: {STATUS}",
905 "STATUS", response->payload[0]);
Chris Cainbae4d072022-02-28 09:46:50 -0600906 pldmIface->pldmClose();
907 return -1;
908 }
909
910 // Decode the response
911 uint8_t compCode = 0, sensorCount = 1;
912 get_sensor_state_field field[6];
913 responseMsgSize -= sizeof(pldm_msg_hdr);
914 auto msgRc = decode_get_state_sensor_readings_resp(
915 response, responseMsgSize, &compCode, &sensorCount, field);
916 if ((msgRc != PLDM_SUCCESS) || (compCode != PLDM_SUCCESS))
917 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500918 lg2::error(
919 "pldmRspCallback: decode_get_state_sensor_readings failed with rc={RC} and compCode={CC}",
920 "RC", msgRc, "CC", compCode);
Chris Cainbae4d072022-02-28 09:46:50 -0600921 pldmIface->pldmClose();
922 return -1;
923 }
924
925 pldmIface->pldmClose();
926
927 const uint8_t instance = pldmIface->pldmResponseOcc;
928 const uint8_t occSensorState = field[0].present_state;
929 pldmIface->pldmResponseReceived = true;
930
931 if (occSensorState == PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE)
932 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500933 lg2::info("pldmRspCallback: OCC{INST} is RUNNING", "INST", instance);
Chris Cainf0295f52024-09-12 15:41:14 -0500934 pldmIface->occActiveCallBack(instance, true);
Chris Cainbae4d072022-02-28 09:46:50 -0600935 }
Chris Cain733b2012022-05-04 11:54:06 -0500936 else if (occSensorState ==
937 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT)
938 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500939 lg2::error(
940 "pldmRspCallback: OCC{INST} has now STOPPED and system is in SAFE MODE",
941 "INST", instance);
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500942
943 // Setting safe mode true
944 pldmIface->safeModeCallBack(true);
945
Chris Cainf0295f52024-09-12 15:41:14 -0500946 pldmIface->occActiveCallBack(instance, false);
Chris Cain733b2012022-05-04 11:54:06 -0500947 }
Chris Cain755af102024-02-27 16:09:51 -0600948 else if (occSensorState ==
949 PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED)
Chris Cainbae4d072022-02-28 09:46:50 -0600950 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500951 lg2::info("pldmRspCallback: OCC{INST} is not running", "INST",
952 instance);
Chris Cainf0295f52024-09-12 15:41:14 -0500953 pldmIface->occActiveCallBack(instance, false);
Chris Cain755af102024-02-27 16:09:51 -0600954 }
955 else
956 {
957 const size_t rspLength = responseMsgSize + sizeof(pldm_msg_hdr);
958 std::vector<std::uint8_t> pldmResponse(rspLength);
959 memcpy(&pldmResponse[0], reinterpret_cast<std::uint8_t*>(response),
960 rspLength);
961 if (!throttleTraces)
Chris Cainc9dc4412023-03-06 15:56:34 -0600962 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500963 lg2::warning(
964 "pldmRspCallback: Unexpected State: {STATE} - PLDM response "
965 "({LEN} bytes) for OCC{INST}:",
966 "STATE", occSensorState, "LEN", rspLength, "INST", instance);
Chris Cainc9dc4412023-03-06 15:56:34 -0600967 dump_hex(pldmResponse);
968 }
Chris Cainbae4d072022-02-28 09:46:50 -0600969 }
970
971 return 0;
972};
973
Chris Cainf0295f52024-09-12 15:41:14 -0500974int Interface::pldmResetCallback(sd_event_source* /*es*/,
975 __attribute__((unused)) int fd,
976 uint32_t revents, void* userData)
977{
978 if (!(revents & EPOLLIN))
979 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500980 lg2::info("pldmResetCallback - revents={NUM}", "NUM", lg2::hex,
981 revents);
Chris Cainf0295f52024-09-12 15:41:14 -0500982 return -1;
983 }
984
985 auto pldmIface = static_cast<Interface*>(userData);
986
987 if (!pldmIface->pldmInstanceID)
988 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500989 lg2::error("pldmResetCallback: No outstanding PLDM Instance ID found");
Chris Cainf0295f52024-09-12 15:41:14 -0500990 return -1;
991 }
992
993 uint8_t* responseMsg = nullptr;
994 size_t responseMsgSize{};
995 pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEid);
996
997 if (!throttleTraces)
998 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500999 lg2::info(
1000 "pldmResetCallback: calling pldm_transport_recv_msg() instance:{ID}",
1001 "ID", pldmIface->pldmInstanceID.value());
Chris Cainf0295f52024-09-12 15:41:14 -05001002 }
1003 auto rc = pldm_transport_recv_msg(pldmIface->pldmTransport, &pldmTID,
1004 (void**)&responseMsg, &responseMsgSize);
1005 int lastErrno = errno;
1006 if (rc)
1007 {
1008 if (!throttleTraces)
1009 {
Chris Cain37abe9b2024-10-31 17:20:31 -05001010 lg2::error(
1011 "pldmResetCallback: pldm_transport_recv_msg failed with rc={RC}, errno={ERR}/{STR}",
1012 "RC",
1013 static_cast<std::underlying_type_t<pldm_requester_error_codes>>(
1014 rc),
1015 "ERR", lastErrno, "STR", strerror(lastErrno));
Chris Cainf0295f52024-09-12 15:41:14 -05001016 }
1017 return -1;
1018 }
1019
1020 // We got the response for the PLDM request msg that was sent
1021 if (!throttleTraces)
1022 {
Chris Cain37abe9b2024-10-31 17:20:31 -05001023 lg2::info(
1024 "pldmResetCallback: pldm_transport_recv_msg() rsp was {LEN} bytes",
1025 "LEN", responseMsgSize);
Chris Cainf0295f52024-09-12 15:41:14 -05001026 }
1027
1028 if (pldmIface->pldmRspTimer.isEnabled())
1029 {
1030 // stop PLDM response timer
1031 pldmIface->pldmRspTimer.setEnabled(false);
1032 }
1033
1034 // instance ID should be freed
1035 pldmIface->pldmInstanceID = std::nullopt;
1036
1037 // Set pointer to autodelete
1038 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{
1039 responseMsg, std::free};
1040
1041 auto response = reinterpret_cast<pldm_msg*>(responseMsgPtr.get());
1042 if (response->payload[0] != PLDM_SUCCESS)
1043 {
Chris Cain37abe9b2024-10-31 17:20:31 -05001044 lg2::error(
1045 "pldmResetCallback: Reset FAILED ({MSG}) - payload[0] was not success: {STATUS}",
1046 "MSG", msgType, "STATUS", response->payload[0]);
Chris Cainf0295f52024-09-12 15:41:14 -05001047 pldmIface->pldmClose();
1048
1049 if (msgType == MSG_OCC_RESET)
1050 {
1051 // Retry reset request
Chris Cain37abe9b2024-10-31 17:20:31 -05001052 lg2::error(
1053 "pldmResetCallback: retrying reset request for OCC{INST}",
1054 "INST", resetInstance);
Chris Cainf0295f52024-09-12 15:41:14 -05001055 pldmIface->resetOCC(resetInstance);
1056 }
1057 return -1;
1058 }
1059 else
1060 {
Chris Cain37abe9b2024-10-31 17:20:31 -05001061 lg2::info("pldmResetCallback: Reset has been successfully started");
Chris Cainf0295f52024-09-12 15:41:14 -05001062 }
1063
1064 pldmIface->pldmClose();
1065
1066 pldmIface->pldmResponseReceived = true;
1067
1068 return 0;
1069}
1070
Patrick Williamsd7542c82024-08-16 15:20:28 -04001071std::vector<uint8_t>
1072 Interface::encodeGetStateSensorRequest(uint8_t instance, uint16_t sensorId)
Chris Cainbae4d072022-02-28 09:46:50 -06001073{
Rashmica Guptaaeba51c2023-02-17 12:30:46 +11001074 if (!getPldmInstanceId())
Chris Cain8b508bf2022-05-26 14:01:31 -05001075 {
Chris Cain37abe9b2024-10-31 17:20:31 -05001076 lg2::error("encodeGetStateSensorRequest: failed to getPldmInstanceId");
Chris Cain8b508bf2022-05-26 14:01:31 -05001077 return std::vector<uint8_t>();
1078 }
1079
Chris Cainbae4d072022-02-28 09:46:50 -06001080 bitfield8_t sRearm = {0};
Patrick Williamsd7542c82024-08-16 15:20:28 -04001081 const size_t msgSize =
1082 sizeof(pldm_msg_hdr) + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES;
Chris Cainbae4d072022-02-28 09:46:50 -06001083 std::vector<uint8_t> request(msgSize);
Chris Cain8b508bf2022-05-26 14:01:31 -05001084
Chris Cainbae4d072022-02-28 09:46:50 -06001085 auto msg = reinterpret_cast<pldm_msg*>(request.data());
Rashmica Guptaaeba51c2023-02-17 12:30:46 +11001086 auto msgRc = encode_get_state_sensor_readings_req(pldmInstanceID.value(),
Chris Cain8b508bf2022-05-26 14:01:31 -05001087 sensorId, sRearm, 0, msg);
Chris Cainbae4d072022-02-28 09:46:50 -06001088 if (msgRc != PLDM_SUCCESS)
1089 {
Chris Cain37abe9b2024-10-31 17:20:31 -05001090 lg2::error(
1091 "encodeGetStateSensorRequest: Failed to encode sensorId:{ID} for OCC{INST} (rc={RC})",
1092 "ID", lg2::hex, sensorId, "INST", instance, "RC", msgRc);
Chris Cainbae4d072022-02-28 09:46:50 -06001093 }
1094 return request;
1095}
1096
1097// Initiate query of the specified OCC Active Sensor
1098void Interface::checkActiveSensor(uint8_t instance)
1099{
1100 static bool tracedOnce = false;
1101 if (pldmFd > 0)
1102 {
Chris Cain755af102024-02-27 16:09:51 -06001103 if (!throttleTraces && !tracedOnce)
Chris Caind1b68262022-02-28 09:56:50 -06001104 {
Chris Cain37abe9b2024-10-31 17:20:31 -05001105 lg2::warning(
1106 "checkActiveSensor: already waiting on OCC{INST} (fd={FD})",
1107 "INST", pldmResponseOcc, "FD", pldmFd);
Chris Cainbae4d072022-02-28 09:46:50 -06001108 tracedOnce = true;
Chris Caind1b68262022-02-28 09:56:50 -06001109 }
Chris Cainbae4d072022-02-28 09:46:50 -06001110 return;
1111 }
1112 tracedOnce = false;
1113
1114 if (!isOCCSensorCacheValid())
1115 {
1116 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
1117 sensorToOCCInstance, OCCSensorOffset);
1118 }
1119
1120 // look up sensor id (key) based on instance
1121 auto entry = std::find_if(
1122 sensorToOCCInstance.begin(), sensorToOCCInstance.end(),
1123 [instance](const auto& entry) { return instance == entry.second; });
1124 if (entry != sensorToOCCInstance.end())
1125 {
1126 // Query the OCC Active Sensor state for this instance
Chris Cain755af102024-02-27 16:09:51 -06001127 if (!throttleTraces)
1128 {
Chris Cain37abe9b2024-10-31 17:20:31 -05001129 lg2::info("checkActiveSensor: OCC{INST} / sensorID: {ID}", "INST",
1130 instance, "ID", lg2::hex, entry->first);
Chris Cain755af102024-02-27 16:09:51 -06001131 }
Chris Cainbae4d072022-02-28 09:46:50 -06001132
Chris Cainbae4d072022-02-28 09:46:50 -06001133 // Encode GetStateSensorReadings PLDM message
1134 auto request = encodeGetStateSensorRequest(instance, entry->first);
1135 if (request.empty())
1136 {
1137 return;
1138 }
1139
1140 // Send request to PLDM and setup callback for response
Chris Cainf0295f52024-09-12 15:41:14 -05001141 msgType = MSG_SENSOR_STATUS;
Chris Cainbae4d072022-02-28 09:46:50 -06001142 sendPldm(request, instance, true);
1143 }
1144 else
1145 {
Chris Cain755af102024-02-27 16:09:51 -06001146 if (!throttleTraces)
1147 {
Chris Cain37abe9b2024-10-31 17:20:31 -05001148 lg2::error(
1149 "checkActiveSensor: Unable to find PLDM sensor for OCC{INST}",
1150 "INST", instance);
1151 lg2::info(
Chris Cain755af102024-02-27 16:09:51 -06001152 "checkActiveSensor: fetching STATE_SET_OPERATIONAL_RUNNING_STATUS");
1153 }
Chris Cain8cf74962022-06-29 08:45:16 -05001154 fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS,
1155 sensorToOCCInstance, OCCSensorOffset);
Patrick Williams05e95592021-09-02 09:28:14 -05001156 }
Patrick Williams05e95592021-09-02 09:28:14 -05001157}
1158
Chris Cain755af102024-02-27 16:09:51 -06001159void Interface::setTraceThrottle(const bool throttle)
1160{
1161 if (throttle != throttleTraces)
1162 {
1163 if (throttle)
1164 {
Chris Cain37abe9b2024-10-31 17:20:31 -05001165 lg2::warning("PLDM traces being throttled");
Chris Cain755af102024-02-27 16:09:51 -06001166 }
1167 else
1168 {
Chris Cain37abe9b2024-10-31 17:20:31 -05001169 lg2::info("PLDM traces no longer being throttled");
Chris Cain755af102024-02-27 16:09:51 -06001170 }
1171 throttleTraces = throttle;
1172 }
1173}
1174
Patrick Williams05e95592021-09-02 09:28:14 -05001175} // namespace pldm