xref: /openbmc/dbus-sensors/src/nvidia-gpu/OcpMctpVdm.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 "OcpMctpVdm.hpp"
8 
9 #include <endian.h>
10 
11 #include <cerrno>
12 #include <cstdint>
13 #include <cstring>
14 #include <span>
15 
16 namespace ocp
17 {
18 namespace accelerator_management
19 {
20 
packHeader(uint16_t pciVendorId,const BindingPciVidInfo & hdr,BindingPciVid & msg)21 int packHeader(uint16_t pciVendorId, const BindingPciVidInfo& hdr,
22                BindingPciVid& msg)
23 {
24     if (hdr.ocp_accelerator_management_msg_type !=
25             static_cast<uint8_t>(MessageType::RESPONSE) &&
26         hdr.ocp_accelerator_management_msg_type !=
27             static_cast<uint8_t>(MessageType::REQUEST))
28     {
29         return EINVAL;
30     }
31 
32     if (hdr.instance_id > instanceMax)
33     {
34         return EINVAL;
35     }
36 
37     msg.instance_id = hdr.instance_id & instanceIdBitMask;
38 
39     if (hdr.ocp_accelerator_management_msg_type ==
40         static_cast<uint8_t>(MessageType::REQUEST))
41     {
42         msg.instance_id |= requestBitMask;
43     }
44     else
45     {
46         msg.instance_id &= ~requestBitMask;
47     }
48 
49     msg.pci_vendor_id = htobe16(pciVendorId);
50     msg.instance_id &= ~instanceIdReservedBitMask;
51     msg.ocp_version = ocpVersion & ocpVersionBitMask;
52     msg.ocp_version |= (ocpType << ocpTypeBitOffset) & ocpTypeBitMask;
53     msg.ocp_accelerator_management_msg_type = hdr.msg_type;
54 
55     return 0;
56 }
57 
decodeReasonCodeAndCC(const std::span<const uint8_t> buf,CompletionCode & cc,uint16_t & reasonCode)58 int decodeReasonCodeAndCC(const std::span<const uint8_t> buf,
59                           CompletionCode& cc, uint16_t& reasonCode)
60 {
61     if (buf.size() <
62         sizeof(ocp::accelerator_management::CommonNonSuccessResponse))
63     {
64         return EINVAL;
65     }
66 
67     // These expression decodes data communicated over the network
68     // The use of reinterpret_cast enables direct memory access to raw byte
69     // buffers without doing unnecessary data copying
70     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
71     const auto* response = reinterpret_cast<
72         const ocp::accelerator_management::CommonNonSuccessResponse*>(
73         buf.data());
74 
75     cc = static_cast<CompletionCode>(response->completion_code);
76     if (cc == CompletionCode::SUCCESS)
77     {
78         reasonCode = 0;
79         return 0;
80     }
81 
82     // reason code is expected to be present if CC != SUCCESS
83     reasonCode = le16toh(response->reason_code);
84 
85     return 0;
86 }
87 } // namespace accelerator_management
88 } // namespace ocp
89