xref: /openbmc/dbus-sensors/src/nvidia-gpu/NvidiaDriverInformation.cpp (revision b341fa2b68ff4d10c3eca0f58a16448b475d1cff)
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