xref: /openbmc/dbus-sensors/src/nvidia-gpu/NvidiaGpuPowerPeakReading.cpp (revision 6b7123225fc4a5180faf89190e9f64a7e248e697)
1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION &
3  * AFFILIATES. All rights reserved.
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "NvidiaGpuPowerPeakReading.hpp"
8 
9 #include "MctpRequester.hpp"
10 #include "Utils.hpp"
11 
12 #include <bits/basic_string.h>
13 
14 #include <NvidiaDeviceDiscovery.hpp>
15 #include <NvidiaGpuMctpVdm.hpp>
16 #include <OcpMctpVdm.hpp>
17 #include <phosphor-logging/lg2.hpp>
18 #include <sdbusplus/asio/object_server.hpp>
19 
20 #include <cstdint>
21 #include <functional>
22 #include <memory>
23 #include <string>
24 
25 using namespace std::literals;
26 
NvidiaGpuPowerPeakReading(mctp::MctpRequester & mctpRequester,const std::string & name,uint8_t eid,uint8_t sensorId,sdbusplus::asio::object_server & objectServer)27 NvidiaGpuPowerPeakReading::NvidiaGpuPowerPeakReading(
28     mctp::MctpRequester& mctpRequester, const std::string& name, uint8_t eid,
29     uint8_t sensorId, sdbusplus::asio::object_server& objectServer) :
30     eid(eid), sensorId{sensorId}, mctpRequester(mctpRequester),
31     objectServer(objectServer)
32 {
33     std::string dbusPath = sensorPathPrefix + "power/"s + escapeName(name);
34 
35     telemetryReportInterface = objectServer.add_interface(
36         dbusPath, "xyz.openbmc_project.Telemetry.Report");
37 
38     std::get<0>(readings) = 0;
39     // Reading from the device is in milliwatts and unit set on the dbus
40     // is watts.
41     std::get<1>(readings).emplace_back("PeakReading", "", 0.0, 0);
42 
43     telemetryReportInterface->register_property("Readings", readings);
44 
45     telemetryReportInterface->initialize();
46 }
47 
~NvidiaGpuPowerPeakReading()48 NvidiaGpuPowerPeakReading::~NvidiaGpuPowerPeakReading()
49 {
50     objectServer.remove_interface(telemetryReportInterface);
51 }
52 
processResponse(int sendRecvMsgResult)53 void NvidiaGpuPowerPeakReading::processResponse(int sendRecvMsgResult)
54 {
55     if (sendRecvMsgResult != 0)
56     {
57         lg2::error(
58             "Error updating Peak Power Sensor for eid {EID} and sensor id {SID} : sending message over MCTP failed, rc={RC}",
59             "EID", eid, "SID", sensorId, "RC", sendRecvMsgResult);
60         return;
61     }
62 
63     ocp::accelerator_management::CompletionCode cc{};
64     uint16_t reasonCode = 0;
65     uint32_t peakPower = 0;
66 
67     const int rc =
68         gpu::decodeGetPowerDrawResponse(response, cc, reasonCode, peakPower);
69 
70     if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS)
71     {
72         lg2::error(
73             "Error updating Peak Power Sensor eid {EID} and sensor id {SID} : decode failed, rc={RC}, cc={CC}, reasonCode={RESC}",
74             "EID", eid, "SID", sensorId, "RC", rc, "CC", cc, "RESC",
75             reasonCode);
76         return;
77     }
78 
79     // Reading from the device is in milliwatts and unit set on the dbus
80     // is watts.
81     std::get<2>(std::get<1>(readings)[0]) = peakPower / 1000.0;
82 
83     telemetryReportInterface->set_property("Readings", readings);
84 }
85 
update()86 void NvidiaGpuPowerPeakReading::update()
87 {
88     const int rc = gpu::encodeGetPowerDrawRequest(
89         gpu::PlatformEnvironmentalCommands::GET_MAX_OBSERVED_POWER, 0, sensorId,
90         averagingInterval, request);
91 
92     if (rc != 0)
93     {
94         lg2::error(
95             "Error updating Peak Power Sensor for eid {EID} and sensor id {SID} : encode failed, rc={RC}",
96             "EID", eid, "SID", sensorId, "RC", rc);
97     }
98 
99     mctpRequester.sendRecvMsg(
100         eid, request, response,
101         [this](int sendRecvMsgResult) { processResponse(sendRecvMsgResult); });
102 }
103