xref: /openbmc/dbus-sensors/src/intel-cpu/IntelCPUSensor.hpp (revision 18b6186e531ae37dd22b634c6530f793528473f4)
1 #pragma once
2 
3 #include "Thresholds.hpp"
4 #include "Utils.hpp"
5 
6 #include <boost/asio/io_context.hpp>
7 #include <boost/asio/posix/stream_descriptor.hpp>
8 #include <boost/asio/steady_timer.hpp>
9 #include <boost/asio/streambuf.hpp>
10 #include <boost/container/flat_map.hpp>
11 #include <gpiod.hpp>
12 #include <sdbusplus/asio/connection.hpp>
13 #include <sdbusplus/asio/object_server.hpp>
14 #include <sensor.hpp>
15 
16 #include <cstddef>
17 #include <cstdint>
18 #include <iostream>
19 #include <memory>
20 #include <string>
21 #include <system_error>
22 #include <variant>
23 #include <vector>
24 
25 class IntelCPUSensor :
26     public Sensor,
27     public std::enable_shared_from_this<IntelCPUSensor>
28 {
29   public:
30     IntelCPUSensor(const std::string& path, const std::string& objectType,
31                    sdbusplus::asio::object_server& objectServer,
32                    std::shared_ptr<sdbusplus::asio::connection>& conn,
33                    boost::asio::io_context& io, const std::string& sensorName,
34                    std::vector<thresholds::Threshold>&& thresholds,
35                    const std::string& configuration, int cpuId, bool show,
36                    double dtsOffset);
37     ~IntelCPUSensor() override;
38     static constexpr unsigned int sensorScaleFactor = 1000;
39     static constexpr unsigned int sensorPollMs = 1000;
40     static constexpr size_t warnAfterErrorCount = 10;
41     static constexpr const char* labelTcontrol = "Tcontrol";
42     void setupRead();
43 
44   private:
45     sdbusplus::asio::object_server& objServer;
46     boost::asio::streambuf readBuf;
47     boost::asio::posix::stream_descriptor inputDev;
48     boost::asio::steady_timer waitTimer;
49     std::string nameTcontrol;
50     std::string path;
51     double privTcontrol;
52     double dtsOffset;
53     bool show;
54     size_t pollTime;
55     bool loggedInterfaceDown = false;
56     uint8_t minMaxReadCounter{0};
57     int fd{};
58     void handleResponse(const boost::system::error_code& err);
59     void checkThresholds() override;
60     void updateMinMaxValues();
61     void restartRead();
62 };
63 
64 extern boost::container::flat_map<std::string, std::shared_ptr<IntelCPUSensor>>
65     gCpuSensors;
66 
67 // this is added to intelcpusensor.hpp to avoid having every sensor have to link
68 // against libgpiod, if another sensor needs it we may move it to utils
cpuIsPresent(const SensorBaseConfigMap & gpioConfig)69 inline bool cpuIsPresent(const SensorBaseConfigMap& gpioConfig)
70 {
71     static boost::container::flat_map<std::string, bool> cpuPresence;
72 
73     auto findName = gpioConfig.find("Name");
74     if (findName == gpioConfig.end())
75     {
76         return false;
77     }
78     std::string gpioName =
79         std::visit(VariantToStringVisitor(), findName->second);
80 
81     auto findIndex = cpuPresence.find(gpioName);
82     if (findIndex != cpuPresence.end())
83     {
84         return findIndex->second;
85     }
86 
87     bool activeHigh = true;
88     auto findPolarity = gpioConfig.find("Polarity");
89     if (findPolarity != gpioConfig.end())
90     {
91         if (std::string("Low") ==
92             std::visit(VariantToStringVisitor(), findPolarity->second))
93         {
94             activeHigh = false;
95         }
96     }
97 
98     auto line = gpiod::find_line(gpioName);
99     if (!line)
100     {
101         std::cerr << "Error requesting gpio: " << gpioName << "\n";
102         return false;
103     }
104 
105     bool resp = false;
106     try
107     {
108         line.request({"cpusensor", gpiod::line_request::DIRECTION_INPUT,
109                       activeHigh ? 0 : gpiod::line_request::FLAG_ACTIVE_LOW});
110         resp = (line.get_value() != 0);
111     }
112     catch (const std::system_error&)
113     {
114         std::cerr << "Error reading gpio: " << gpioName << "\n";
115         return false;
116     }
117 
118     cpuPresence[gpioName] = resp;
119 
120     return resp;
121 }
122