1 /*
2 * SPDX-FileCopyrightText: Copyright OpenBMC Authors
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include "NvidiaDriverInformation.hpp"
7
8 #include "Utils.hpp"
9
10 #include <MctpRequester.hpp>
11 #include <NvidiaGpuMctpVdm.hpp>
12 #include <OcpMctpVdm.hpp>
13 #include <phosphor-logging/lg2.hpp>
14 #include <sdbusplus/asio/connection.hpp>
15 #include <sdbusplus/asio/object_server.hpp>
16 #include <sdbusplus/message/native_types.hpp>
17
18 #include <cstdint>
19 #include <memory>
20 #include <span>
21 #include <string>
22 #include <system_error>
23 #include <vector>
24
25 const std::string softwareInventoryPath = "/xyz/openbmc_project/software/";
26
NvidiaDriverInformation(std::shared_ptr<sdbusplus::asio::connection> & conn,mctp::MctpRequester & mctpRequester,const std::string & name,const sdbusplus::message::object_path & path,const uint8_t eid,sdbusplus::asio::object_server & objectServer)27 NvidiaDriverInformation::NvidiaDriverInformation(
28 std::shared_ptr<sdbusplus::asio::connection>& conn,
29 mctp::MctpRequester& mctpRequester, const std::string& name,
30 const sdbusplus::message::object_path& path, const uint8_t eid,
31 sdbusplus::asio::object_server& objectServer) :
32 eid(eid), conn(conn), mctpRequester(mctpRequester)
33 {
34 const std::string dbusPath = softwareInventoryPath + escapeName(name);
35
36 versionInterface = objectServer.add_interface(
37 dbusPath, "xyz.openbmc_project.Software.Version");
38
39 versionInterface->register_property<std::string>("Version", "");
40
41 versionInterface->register_property<std::string>(
42 "Purpose", "xyz.openbmc_project.Software.Version.VersionPurpose.Other");
43
44 if (!versionInterface->initialize())
45 {
46 lg2::error(
47 "Failed to initialize Version interface for Driver Information for eid {EID}",
48 "EID", eid);
49 }
50
51 std::vector<Association> associations;
52 associations.emplace_back("running", "ran_on", path.parent_path());
53
54 associationInterface =
55 objectServer.add_interface(dbusPath, association::interface);
56
57 associationInterface->register_property("Associations", associations);
58
59 if (!associationInterface->initialize())
60 {
61 lg2::error(
62 "Failed to initialize Association interface for Driver Information for eid {EID}",
63 "EID", eid);
64 }
65 }
66
processResponse(const std::error_code & ec,std::span<const uint8_t> buffer)67 void NvidiaDriverInformation::processResponse(const std::error_code& ec,
68 std::span<const uint8_t> buffer)
69 {
70 if (ec)
71 {
72 lg2::error(
73 "Error updating Driver Information for eid {EID} : sending message over MCTP failed, rc={RC}",
74 "EID", eid, "RC", ec.message());
75 return;
76 }
77
78 ocp::accelerator_management::CompletionCode cc{};
79 uint16_t reasonCode = 0;
80 gpu::DriverState driverState{};
81 std::string driverVersion;
82
83 const int rc = gpu::decodeGetDriverInformationResponse(
84 buffer, cc, reasonCode, driverState, driverVersion);
85
86 if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS)
87 {
88 lg2::error(
89 "Error updating Driver Information for eid {EID} : decode failed, rc={RC}, cc={CC}, reasonCode={REASON}",
90 "EID", eid, "RC", rc, "CC", static_cast<uint8_t>(cc), "REASON",
91 reasonCode);
92 return;
93 }
94
95 versionInterface->set_property("Version", driverVersion);
96 }
97
update()98 void NvidiaDriverInformation::update()
99 {
100 const int rc = gpu::encodeGetDriverInformationRequest(0, request);
101
102 if (rc != 0)
103 {
104 lg2::error(
105 "Error updating Driver Information for eid {EID} : encode failed, rc={RC}",
106 "EID", eid, "RC", rc);
107 return;
108 }
109
110 mctpRequester.sendRecvMsg(
111 eid, request,
112 [weak{weak_from_this()}](const std::error_code& ec,
113 std::span<const uint8_t> buffer) {
114 std::shared_ptr<NvidiaDriverInformation> self = weak.lock();
115 if (!self)
116 {
117 lg2::error("invalid reference to NvidiaDriverInformation");
118 return;
119 }
120 self->processResponse(ec, buffer);
121 });
122 }
123