blob: df6f19971ef81d13ab0f4958351a1b5ac88a17f5 [file] [log] [blame]
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +05301#pragma once
2
3#include <cstring>
4#include <vector>
5#include <experimental/filesystem>
6#include <functional>
7#include <sdbusplus/bus.hpp>
Vishwanatha Subbanna2dc9b1a2017-08-18 18:29:41 +05308#include <phosphor-logging/log.hpp>
9#include <phosphor-logging/elog.hpp>
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050010#include <powercap.hpp>
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053011#include "occ_pass_through.hpp"
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +053012#include "occ_status.hpp"
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050013#include "occ_finder.hpp"
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053014#include "config.h"
15
16namespace sdbusRule = sdbusplus::bus::match::rules;
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053017namespace open_power
18{
19namespace occ
20{
21
22/** @class Manager
23 * @brief Builds and manages OCC objects
24 */
25struct Manager
26{
27 public:
28 Manager() = delete;
29 Manager(const Manager&) = delete;
30 Manager& operator=(const Manager&) = delete;
31 Manager(Manager&&) = default;
32 Manager& operator=(Manager&&) = default;
33 ~Manager() = default;
34
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +053035 /** @brief Adds OCC pass-through and status objects on the bus
36 * when corresponding CPU inventory is created.
Vishwanatha Subbannaee4d83d2017-06-29 18:35:00 +053037 *
38 * @param[in] bus - handle to the bus
39 * @param[in] event - Unique ptr reference to sd_event
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053040 */
Vishwanatha Subbannaee4d83d2017-06-29 18:35:00 +053041 Manager(sdbusplus::bus::bus& bus,
42 EventPtr& event) :
43 bus(bus),
44 event(event)
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053045 {
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050046 // Check if CPU inventory exists already.
47 auto occs = open_power::occ::finder::get();
48 if (occs.empty())
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053049 {
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050050 // Need to watch for CPU inventory creation.
51 for (auto id = 0; id < MAX_CPUS; ++id)
52 {
53 auto path = std::string(CPU_PATH) + std::to_string(id);
54 cpuMatches.emplace_back(
55 bus,
56 sdbusRule::interfacesAdded() +
57 sdbusRule::argNpath(0, path),
58 std::bind(std::mem_fn(&Manager::cpuCreated),
59 this, std::placeholders::_1));
60 }
61 }
62 else
63 {
64 for (const auto& occ : occs)
65 {
66 // CPU inventory exists already, OCC objects can be created.
67 createObjects(occ);
68 }
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053069 }
70 }
71
Vishwanatha Subbanna2dc9b1a2017-08-18 18:29:41 +053072 private:
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053073 /** @brief Callback that responds to cpu creation in the inventory -
Vishwanatha Subbannaee4d83d2017-06-29 18:35:00 +053074 * by creating the needed objects.
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053075 *
76 * @param[in] msg - bus message
77 *
78 * @returns 0 to indicate success
79 */
80 int cpuCreated(sdbusplus::message::message& msg)
81 {
82 namespace fs = std::experimental::filesystem;
83
84 sdbusplus::message::object_path o;
85 msg.read(o);
86 fs::path cpuPath(std::string(std::move(o)));
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053087
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050088 auto name = cpuPath.filename().string();
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053089 auto index = name.find(CPU_NAME);
90 name.replace(index, std::strlen(CPU_NAME), OCC_NAME);
91
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050092 createObjects(name);
93
94 return 0;
95 }
96
Deepak Kodihalli5f031f32017-07-26 08:25:59 -050097 /** @brief Create child OCC objects.
98 *
99 * @param[in] occ - the occ name, such as occ0.
100 */
101 void createObjects(const std::string& occ)
102 {
103 auto path = fs::path(OCC_CONTROL_ROOT) / occ;
104
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +0530105 passThroughObjects.emplace_back(
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +0530106 std::make_unique<PassThrough>(
107 bus,
108 path.c_str()));
109
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +0530110 statusObjects.emplace_back(
111 std::make_unique<Status>(
112 bus,
Vishwanatha Subbannaee4d83d2017-06-29 18:35:00 +0530113 event,
Vishwanatha Subbanna2dc9b1a2017-08-18 18:29:41 +0530114 path.c_str(),
115 std::bind(std::mem_fn(&Manager::statusCallBack),
116 this, std::placeholders::_1)));
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500117
118 // Create the power cap monitor object for master occ (0)
Deepak Kodihalli5f031f32017-07-26 08:25:59 -0500119 if (!pcap)
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500120 {
121 pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
122 bus,
Deepak Kodihalli5f031f32017-07-26 08:25:59 -0500123 *statusObjects.front());
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500124 }
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +0530125 }
126
Vishwanatha Subbanna2dc9b1a2017-08-18 18:29:41 +0530127 /** @brief Callback handler invoked by Status object when the OccActive
128 * property is changed. This is needed to make sure that the
129 * error detection is started only after all the OCCs are bound.
130 * Similarly, when one of the OCC gets its OccActive property
131 * un-set, then the OCC error detection needs to be stopped on
132 * all the OCCs
133 *
134 * @param[in] status - OccActive status
135 */
136 void statusCallBack(bool status)
137 {
138 using namespace phosphor::logging;
139 using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
140 Error::InternalFailure;
141
142 // At this time, it won't happen but keeping it
143 // here just in case something changes in the future
144 if ((activeCount == 0) && (!status))
145 {
146 log<level::ERR>("Invalid update on OCCActive");
147 elog<InternalFailure>();
148 }
149
150 activeCount += status ? 1 : -1;
151
152 // If all the OCCs are bound, then start error detection
153 if (activeCount == statusObjects.size())
154 {
155 for (const auto& occ: statusObjects)
156 {
157 occ->addErrorWatch();
158 }
159 }
160 else if (!status)
161 {
162 // If some OCCs are not bound yet, those will be a NO-OP
163 for (const auto& occ: statusObjects)
164 {
165 occ->removeErrorWatch();
166 }
167 }
168 }
169
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +0530170 /** @brief reference to the bus */
171 sdbusplus::bus::bus& bus;
172
Vishwanatha Subbannaee4d83d2017-06-29 18:35:00 +0530173 /** @brief reference to sd_event wrapped in unique_ptr */
174 EventPtr& event;
175
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +0530176 /** @brief OCC pass-through objects */
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +0530177 std::vector<std::unique_ptr<PassThrough>> passThroughObjects;
178
179 /** @brief OCC Status objects */
180 std::vector<std::unique_ptr<Status>> statusObjects;
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +0530181
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500182 /** @brief Power cap monitor and occ notification object */
183 std::unique_ptr<open_power::occ::powercap::PowerCap> pcap;
184
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +0530185 /** @brief sbdbusplus match objects */
186 std::vector<sdbusplus::bus::match_t> cpuMatches;
Vishwanatha Subbanna2dc9b1a2017-08-18 18:29:41 +0530187
188 /** @brief Number of OCCs that are bound */
189 uint8_t activeCount = 0;
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +0530190};
191
192} // namespace occ
193} // namespace open_power