1 #pragma once
2 
3 #include "config.h"
4 
5 #include "utils.hpp"
6 
7 #include <sdbusplus/bus.hpp>
8 #include <sdbusplus/bus/match.hpp>
9 
10 #include <filesystem>
11 #include <regex>
12 
13 namespace open_power
14 {
15 namespace occ
16 {
17 class Status;
18 
19 namespace powercap
20 {
21 
22 namespace sdbusRule = sdbusplus::bus::match::rules;
23 namespace fs = std::filesystem;
24 
25 /** @class PowerCap
26  *  @brief Monitors for changes to the power cap and notifies occ
27  *
28  *  The customer power cap is provided to the OCC by host TMGT when the occ
29  *  first goes active or is reset.  This code is responsible for sending
30  *  the power cap to the OCC if the cap is changed while the occ is active.
31  */
32 
33 class PowerCap
34 {
35   public:
36     /** @brief PowerCap object to inform occ of changes to cap
37      *
38      * This object will monitor for changes to the power cap setting and
39      * power cap enable properties.  If a change is detected, and the occ
40      * is active, then this object will notify the OCC of the change.
41      *
42      * @param[in] occStatus - The occ status object
43      */
PowerCap(Status & occStatus)44     explicit PowerCap(Status& occStatus) :
45         occStatus(occStatus),
46         pcapMatch(
47             utils::getBus(),
48             sdbusRule::member("PropertiesChanged") +
49                 sdbusRule::path(
50                     "/xyz/openbmc_project/control/host0/power_cap") +
51                 sdbusRule::argN(0, "xyz.openbmc_project.Control.Power.Cap") +
52                 sdbusRule::interface("org.freedesktop.DBus.Properties"),
53             std::bind(std::mem_fn(&PowerCap::pcapChanged), this,
54                       std::placeholders::_1)){};
55 
56     /** @brief Return the appropriate value to write to the OCC (output/DC
57      * power)
58      *
59      * @param[in]  pcap        - Current user power cap setting (input/AC power)
60      * @param[in]  pcapEnabled - Current power cap enable setting
61      *
62      * @return The value to write to the occ user pcap
63      */
64     uint32_t getOccInput(uint32_t pcap, bool pcapEnabled);
65 
66     /** @brief Read the power cap bounds from sysfs and update DBus */
67     void updatePcapBounds();
68 
69   private:
70     /** @brief Callback for pcap setting changes
71      *
72      * Process change and inform OCC
73      *
74      * @param[in]  msg       - Data associated with pcap change signal
75      *
76      */
77     void pcapChanged(sdbusplus::message_t& msg);
78 
79     /** @brief Get the power cap property
80      *
81      * @return Power cap, 0 on failure to indicate no pcap
82      */
83     uint32_t getPcap();
84 
85     /** @brief Get the power cap enable property
86      *
87      * @return Whether power cap enabled, will return false on error
88      */
89     bool getPcapEnabled();
90 
91     /** @brief Write the output/DC power cap to the occ hwmon entry
92      *
93      * @param[in]  pcapValue - Power cap value to write to OCC
94      */
95     void writeOcc(uint32_t pcapValue);
96 
97     /** @brief Read the user power cap from sysfs
98      *
99      * @return User power cap value in Watts or 0 if disabled
100      */
101     uint32_t readUserCapHwmon();
102 
103     /**
104      * @brief Returns the filename to use for the user power cap
105      *
106      * The file is of the form "powerX_cap_user", where X is any
107      * number.
108      *
109      * @param[in] expr - Regular expression of file to find
110      *
111      * @return full path/filename, or empty path if not found.
112      */
113     fs::path getPcapFilename(const std::regex& expr);
114 
115     /* @brief OCC Status object */
116     Status& occStatus;
117 
118     /** @brief Used to subscribe to dbus pcap property changes **/
119     sdbusplus::bus::match_t pcapMatch;
120 
121     /** @brief Path to the sysfs files holding the cap properties **/
122     fs::path pcapBasePathname;
123 
124     /** @brief Update the power cap bounds on DBus
125      *
126      * @param[in]  softMin - soft minimum power cap in Watts
127      * @param[in]  hardMin - hard minimum power cap in Watts
128      * @param[in]  pcapMax - maximum power cap in Watts
129      *
130      * @return true if all parms were written successfully
131      */
132     bool updateDbusPcapLimits(uint32_t softMin, uint32_t hardMin,
133                               uint32_t pcapMax);
134 
135     /** @brief Read the power cap bounds from DBus
136      *
137      * @param[out]  softMin - soft minimum power cap in Watts
138      * @param[out]  hardMin - hard minimum power cap in Watts
139      * @param[out]  pcapMax - maximum power cap in Watts
140      *
141      * @return true if all parms were read successfully
142      *         If a parm is not successfully read, it will default to 0 for the
143      *           Min parameter and INT_MAX for the Max parameter
144      */
145     bool readDbusPcapLimits(uint32_t& softMin, uint32_t& hardMin,
146                             uint32_t& max);
147 };
148 
149 } // namespace powercap
150 
151 } // namespace occ
152 
153 } // namespace open_power
154