blob: 7e8c0dbab045120267b703afea47bb5aa31492e1 [file] [log] [blame]
Andrew Geissler32016d12017-06-20 15:46:52 -05001#include <powercap.hpp>
2#include <phosphor-logging/log.hpp>
3
4namespace open_power
5{
6namespace occ
7{
8namespace powercap
9{
10
Andrew Geissler52cf26a2017-07-06 12:56:32 -050011constexpr auto PCAP_PATH = "/xyz/openbmc_project/control/host0/power_cap";
12constexpr auto PCAP_INTERFACE = "xyz.openbmc_project.Control.Power.Cap";
13
14constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
15constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
16constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
17
18constexpr auto POWER_CAP_PROP = "PowerCap";
19constexpr auto POWER_CAP_ENABLE_PROP = "PowerCapEnable";
20
Andrew Geissler32016d12017-06-20 15:46:52 -050021using namespace phosphor::logging;
22
Andrew Geissler52cf26a2017-07-06 12:56:32 -050023std::string PowerCap::getService(std::string path,
24 std::string interface)
25{
26 auto mapper = bus.new_method_call(MAPPER_BUSNAME,
27 MAPPER_PATH,
28 MAPPER_INTERFACE,
29 "GetObject");
30
31 mapper.append(path, std::vector<std::string>({interface}));
32 auto mapperResponseMsg = bus.call(mapper);
33
34 if (mapperResponseMsg.is_method_error())
35 {
36 log<level::ERR>("Error in mapper call",
37 entry("PATH=%s", path.c_str()),
38 entry("INTERFACE=%s", interface.c_str()));
39 // TODO openbmc/openbmc#851 - Once available, throw returned error
40 throw std::runtime_error("Error in mapper call");
41 }
42
43 std::map<std::string, std::vector<std::string>> mapperResponse;
44 mapperResponseMsg.read(mapperResponse);
45 if (mapperResponse.empty())
46 {
47 log<level::ERR>("Error reading mapper response",
48 entry("PATH=%s", path.c_str()),
49 entry("INTERFACE=%s", interface.c_str()));
50 // TODO openbmc/openbmc#1712 - Handle empty mapper resp. consistently
51 throw std::runtime_error("Error reading mapper response");
52 }
53
54 return mapperResponse.begin()->first;
55}
56
Andrew Geissler4cea4d22017-07-10 15:13:33 -050057uint32_t PowerCap::getOccInput(uint32_t pcap, bool pcapEnabled)
58{
59 if (!pcapEnabled)
60 {
61 // Pcap disabled, return 0 to indicate disabled
62 return 0;
63 }
64
65 // If pcap is not disabled then just return the pcap with the derating
66 // factor applied.
67 return( (static_cast<uint64_t>(pcap) * PS_DERATING_FACTOR) /100);
68}
69
Andrew Geissler52cf26a2017-07-06 12:56:32 -050070uint32_t PowerCap::getPcap()
71{
72 auto settingService = getService(PCAP_PATH,PCAP_INTERFACE);
73
74 auto method = this->bus.new_method_call(settingService.c_str(),
75 PCAP_PATH,
76 "org.freedesktop.DBus.Properties",
77 "Get");
78
79 method.append(PCAP_INTERFACE, POWER_CAP_PROP);
80 auto reply = this->bus.call(method);
81
82 if (reply.is_method_error())
83 {
84 log<level::ERR>("Error in getPcap prop");
85 return 0;
86 }
87 sdbusplus::message::variant<uint32_t> pcap;
88 reply.read(pcap);
89
90 return pcap.get<uint32_t>();
91}
92
93bool PowerCap::getPcapEnabled()
94{
95 auto settingService = getService(PCAP_PATH,PCAP_INTERFACE);
96
97 auto method = this->bus.new_method_call(settingService.c_str(),
98 PCAP_PATH,
99 "org.freedesktop.DBus.Properties",
100 "Get");
101
102 method.append(PCAP_INTERFACE, POWER_CAP_ENABLE_PROP);
103 auto reply = this->bus.call(method);
104
105 if (reply.is_method_error())
106 {
107 log<level::ERR>("Error in getPcapEnabled prop");
108 return 0;
109 }
110 sdbusplus::message::variant<bool> pcapEnabled;
111 reply.read(pcapEnabled);
112
113 return pcapEnabled.get<bool>();
114}
Andrew Geissler32016d12017-06-20 15:46:52 -0500115
116void PowerCap::pcapChanged(sdbusplus::message::message& msg)
117{
Andrew Geissler32016d12017-06-20 15:46:52 -0500118 if (!occStatus.occActive())
119 {
120 // Nothing to do
121 return;
122 }
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500123
124 uint32_t pcap = 0;
125 bool pcapEnabled = false;
126
127 std::string msgSensor;
128 std::map<std::string, sdbusplus::message::variant<uint32_t, bool>> msgData;
129 msg.read(msgSensor, msgData);
130
131 // Retrieve which property changed via the msg and read the other one
132 auto valPropMap = msgData.find(POWER_CAP_PROP);
133 if (valPropMap != msgData.end())
134 {
135 pcap = sdbusplus::message::variant_ns::get<uint32_t>(
136 valPropMap->second);
137 pcapEnabled = getPcapEnabled();
138 }
139 else
140 {
141 valPropMap = msgData.find(POWER_CAP_ENABLE_PROP);
142 if (valPropMap != msgData.end())
143 {
144 pcapEnabled = sdbusplus::message::variant_ns::get<bool>(
145 valPropMap->second);
146 pcap = getPcap();
147 }
148 else
149 {
150 log<level::INFO>("Unknown power cap property changed");
151 return;
152 }
153 }
154
155 log<level::INFO>("Power Cap Property Change",
156 entry("PCAP=%u",pcap),
157 entry("PCAP_ENABLED=%u",pcapEnabled));
158
159 // Determine desired action to write to occ
Andrew Geissler4cea4d22017-07-10 15:13:33 -0500160 auto occInput = getOccInput(pcap, pcapEnabled);
161 log<level::DEBUG>("Writing new power cap setting to OCC",
162 entry("OCC_PCAP_VAL=%u",occInput));
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500163
164 // Write action to occ
165 // TODO
166
167 return;
Andrew Geissler32016d12017-06-20 15:46:52 -0500168}
169
170} // namespace open_power
171
172} // namespace occ
173
174}// namespace powercap