xref: /openbmc/dbus-sensors/src/nvidia-gpu/NvidiaGpuMctpVdm.cpp (revision 560e6af7b1f74e9c020a0f82817f9d926e0c4f72)
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 "NvidiaGpuMctpVdm.hpp"
8 
9 #include "OcpMctpVdm.hpp"
10 
11 #include <endian.h>
12 
13 #include <cerrno>
14 #include <cstdint>
15 #include <cstring>
16 #include <span>
17 
18 namespace gpu
19 {
20 // These functions encode/decode data communicated over the network
21 // The use of reinterpret_cast enables direct memory access to raw byte buffers
22 // without doing unnecessary data copying
23 // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast)
packHeader(const ocp::accelerator_management::BindingPciVidInfo & hdr,ocp::accelerator_management::BindingPciVid & msg)24 int packHeader(const ocp::accelerator_management::BindingPciVidInfo& hdr,
25                ocp::accelerator_management::BindingPciVid& msg)
26 {
27     return ocp::accelerator_management::packHeader(nvidiaPciVendorId, hdr, msg);
28 }
29 
encodeQueryDeviceIdentificationRequest(uint8_t instanceId,const std::span<uint8_t> buf)30 int encodeQueryDeviceIdentificationRequest(uint8_t instanceId,
31                                            const std::span<uint8_t> buf)
32 {
33     if (buf.size() < sizeof(QueryDeviceIdentificationRequest))
34     {
35         return EINVAL;
36     }
37 
38     auto* msg = reinterpret_cast<QueryDeviceIdentificationRequest*>(buf.data());
39 
40     ocp::accelerator_management::BindingPciVidInfo header{};
41 
42     header.ocp_accelerator_management_msg_type =
43         static_cast<uint8_t>(ocp::accelerator_management::MessageType::REQUEST);
44     header.instance_id = instanceId &
45                          ocp::accelerator_management::instanceIdBitMask;
46     header.msg_type =
47         static_cast<uint8_t>(MessageType::DEVICE_CAPABILITY_DISCOVERY);
48 
49     auto rc = packHeader(header, msg->hdr.msgHdr.hdr);
50 
51     if (rc != 0)
52     {
53         return rc;
54     }
55 
56     msg->hdr.command = static_cast<uint8_t>(
57         DeviceCapabilityDiscoveryCommands::QUERY_DEVICE_IDENTIFICATION);
58     msg->hdr.data_size = 0;
59 
60     return 0;
61 }
62 
decodeQueryDeviceIdentificationResponse(const std::span<const uint8_t> buf,ocp::accelerator_management::CompletionCode & cc,uint16_t & reasonCode,uint8_t & deviceIdentification,uint8_t & deviceInstance)63 int decodeQueryDeviceIdentificationResponse(
64     const std::span<const uint8_t> buf,
65     ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode,
66     uint8_t& deviceIdentification, uint8_t& deviceInstance)
67 {
68     auto rc =
69         ocp::accelerator_management::decodeReasonCodeAndCC(buf, cc, reasonCode);
70 
71     if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS)
72     {
73         return rc;
74     }
75 
76     if (buf.size() < sizeof(QueryDeviceIdentificationResponse))
77     {
78         return EINVAL;
79     }
80 
81     const auto* response =
82         reinterpret_cast<const QueryDeviceIdentificationResponse*>(buf.data());
83 
84     deviceIdentification = response->device_identification;
85     deviceInstance = response->instance_id;
86 
87     return 0;
88 }
89 
encodeGetTemperatureReadingRequest(uint8_t instanceId,uint8_t sensorId,std::span<uint8_t> buf)90 int encodeGetTemperatureReadingRequest(uint8_t instanceId, uint8_t sensorId,
91                                        std::span<uint8_t> buf)
92 {
93     if (buf.size() < sizeof(GetTemperatureReadingRequest))
94     {
95         return EINVAL;
96     }
97 
98     auto* msg = reinterpret_cast<GetTemperatureReadingRequest*>(buf.data());
99 
100     ocp::accelerator_management::BindingPciVidInfo header{};
101     header.ocp_accelerator_management_msg_type =
102         static_cast<uint8_t>(ocp::accelerator_management::MessageType::REQUEST);
103     header.instance_id = instanceId &
104                          ocp::accelerator_management::instanceIdBitMask;
105     header.msg_type = static_cast<uint8_t>(MessageType::PLATFORM_ENVIRONMENTAL);
106 
107     auto rc = packHeader(header, msg->hdr.msgHdr.hdr);
108 
109     if (rc != 0)
110     {
111         return rc;
112     }
113 
114     msg->hdr.command = static_cast<uint8_t>(
115         PlatformEnvironmentalCommands::GET_TEMPERATURE_READING);
116     msg->hdr.data_size = sizeof(sensorId);
117     msg->sensor_id = sensorId;
118 
119     return 0;
120 }
121 
decodeGetTemperatureReadingResponse(const std::span<const uint8_t> buf,ocp::accelerator_management::CompletionCode & cc,uint16_t & reasonCode,double & temperatureReading)122 int decodeGetTemperatureReadingResponse(
123     const std::span<const uint8_t> buf,
124     ocp::accelerator_management::CompletionCode& cc, uint16_t& reasonCode,
125     double& temperatureReading)
126 {
127     auto rc =
128         ocp::accelerator_management::decodeReasonCodeAndCC(buf, cc, reasonCode);
129 
130     if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS)
131     {
132         return rc;
133     }
134 
135     if (buf.size() < sizeof(GetTemperatureReadingResponse))
136     {
137         return EINVAL;
138     }
139 
140     const auto* response =
141         reinterpret_cast<const GetTemperatureReadingResponse*>(buf.data());
142 
143     uint16_t dataSize = le16toh(response->hdr.data_size);
144 
145     if (dataSize != sizeof(int32_t))
146     {
147         return EINVAL;
148     }
149 
150     int32_t reading = le32toh(response->reading);
151     temperatureReading = reading / static_cast<double>(1 << 8);
152 
153     return 0;
154 }
155 // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast)
156 } // namespace gpu
157