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