diff options
author | Deepak Kodihalli <dkodihal@in.ibm.com> | 2017-07-26 08:25:59 -0500 |
---|---|---|
committer | Deepak Kodihalli <dkodihal@in.ibm.com> | 2017-08-01 10:55:50 -0500 |
commit | 5f031f3c722f0a4d10e562f5cfa54ba32d12958e (patch) | |
tree | 50516eb3c732e38d78cbb49528b5d9800b06da9c | |
parent | ee4d83dfc7b6cf3b5979541ab5b1918b68e6bbdb (diff) | |
download | openpower-occ-control-5f031f3c722f0a4d10e562f5cfa54ba32d12958e.tar.gz openpower-occ-control-5f031f3c722f0a4d10e562f5cfa54ba32d12958e.zip |
Reconstruct OCC objects on app restart
The OCC objects would get created when corresponding CPU inventory items
get added. This doesn't cover a scenario where the OCC app restarts.
If the CPU inventory is already present when the app starts, construct
OCC objects as well.
Resolves openbmc/openbmc#1824.
Change-Id: I4994d93ba6f528ca67977604ccb1da717563092a
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
-rw-r--r-- | Makefile.am | 6 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | occ_finder.cpp | 82 | ||||
-rw-r--r-- | occ_finder.hpp | 20 | ||||
-rw-r--r-- | occ_manager.hpp | 57 |
5 files changed, 151 insertions, 18 deletions
diff --git a/Makefile.am b/Makefile.am index 5042ec5..361af89 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,7 +4,8 @@ noinst_HEADERS = \ occ_status.hpp \ powercap.hpp \ occ_errors.hpp \ - occ_events.hpp + occ_events.hpp \ + occ_finder.hpp sbin_PROGRAMS = openpower-occ-control openpower_occ_control_SOURCES = \ @@ -14,7 +15,8 @@ openpower_occ_control_SOURCES = \ occ_errors.cpp \ app.cpp \ powercap.cpp \ - org/open_power/OCC/Device/error.cpp + org/open_power/OCC/Device/error.cpp \ + occ_finder.cpp BUILT_SOURCES = org/open_power/OCC/Device/error.hpp \ org/open_power/OCC/Device/error.cpp diff --git a/configure.ac b/configure.ac index dadc118..06497f1 100644 --- a/configure.ac +++ b/configure.ac @@ -101,6 +101,10 @@ AC_ARG_VAR(PS_DERATING_FACTOR, [The power supply derating factor]) AS_IF([test "x$PS_DERATING_FACTOR" == "x"], [PS_DERATING_FACTOR=90]) AC_DEFINE_UNQUOTED([PS_DERATING_FACTOR], [$PS_DERATING_FACTOR], [The power supply derating factor]) +AC_ARG_VAR(CPU_SUBPATH, [The subpath containing CPU objects]) +AS_IF([test "x$CPU_SUBPATH" == "x"], [CPU_SUBPATH="/xyz/openbmc_project/inventory/system/chassis/motherboard"]) +AC_DEFINE_UNQUOTED([CPU_SUBPATH], ["$CPU_SUBPATH"], [The subpath containing CPU objects]) + AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile test/Makefile]) AC_OUTPUT diff --git a/occ_finder.cpp b/occ_finder.cpp new file mode 100644 index 0000000..a533067 --- /dev/null +++ b/occ_finder.cpp @@ -0,0 +1,82 @@ +#include <algorithm> +#include <iterator> +#include <experimental/filesystem> +#include <sdbusplus/server.hpp> +#include <phosphor-logging/elog-errors.hpp> +#include <phosphor-logging/log.hpp> +#include <xyz/openbmc_project/Common/error.hpp> +#include "occ_finder.hpp" +#include "config.h" + +namespace open_power +{ +namespace occ +{ +namespace finder +{ + +using namespace phosphor::logging; + +constexpr auto toChar(size_t c) +{ + constexpr auto map = "0123456789abcdef"; + return map[c]; +} + +std::vector<std::string> get() +{ + namespace fs = std::experimental::filesystem; + using Path = std::string; + using Service = std::string; + using Interface = std::string; + using Interfaces = std::vector<Interface>; + + auto bus = sdbusplus::bus::new_default(); + auto mapper = + bus.new_method_call( + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", + "GetSubTree"); + + auto depth = 0; + Path path = CPU_SUBPATH; + Interfaces interfaces{INVENTORY_ITEM_INTERFACE}; + mapper.append(path); + mapper.append(depth); + mapper.append(interfaces); + + auto result = bus.call(mapper); + if (result.is_method_error()) + { + // It's okay to not have inventory, for example at BMC standby + return {}; + } + + using MapperResponse = std::map<Path, std::map<Service, Interfaces>>; + MapperResponse response; + result.read(response); + if (response.empty()) + { + // It's okay to not have inventory, for example at BMC standby + return {}; + } + + std::vector<std::string> occs; + for (auto count = 0; count < MAX_CPUS; ++count) + { + fs::path p(path); + p /= std::string(CPU_NAME) + toChar(count); + if (response.end() != response.find(p.string())) + { + occs.emplace_back(std::string(OCC_NAME) + + toChar(count)); + } + } + + return occs; +} + +} // namespace finder +} // namespace occ +} // namespace open_power diff --git a/occ_finder.hpp b/occ_finder.hpp new file mode 100644 index 0000000..cad8277 --- /dev/null +++ b/occ_finder.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include <vector> +#include <string> + +namespace open_power +{ +namespace occ +{ +namespace finder +{ + +/** @brief Get OCC objects on the system by mapping them to CPU inventory + * @returns vector of occ objects, such as occ0, occ1, and so on. + */ +std::vector<std::string> get(); + +} // namespace finder +} // namespace occ +} // namespace open_power diff --git a/occ_manager.hpp b/occ_manager.hpp index 4430d74..7b76703 100644 --- a/occ_manager.hpp +++ b/occ_manager.hpp @@ -5,10 +5,11 @@ #include <experimental/filesystem> #include <functional> #include <sdbusplus/bus.hpp> +#include <powercap.hpp> #include "occ_pass_through.hpp" #include "occ_status.hpp" +#include "occ_finder.hpp" #include "config.h" -#include <powercap.hpp> namespace sdbusRule = sdbusplus::bus::match::rules; @@ -41,15 +42,29 @@ struct Manager bus(bus), event(event) { - for (auto id = 0; id < MAX_CPUS; ++id) + // Check if CPU inventory exists already. + auto occs = open_power::occ::finder::get(); + if (occs.empty()) { - auto path = std::string(CPU_PATH) + std::to_string(id); - cpuMatches.emplace_back( - bus, - sdbusRule::interfacesAdded() + - sdbusRule::argNpath(0, path), - std::bind(std::mem_fn(&Manager::cpuCreated), - this, std::placeholders::_1)); + // Need to watch for CPU inventory creation. + for (auto id = 0; id < MAX_CPUS; ++id) + { + auto path = std::string(CPU_PATH) + std::to_string(id); + cpuMatches.emplace_back( + bus, + sdbusRule::interfacesAdded() + + sdbusRule::argNpath(0, path), + std::bind(std::mem_fn(&Manager::cpuCreated), + this, std::placeholders::_1)); + } + } + else + { + for (const auto& occ : occs) + { + // CPU inventory exists already, OCC objects can be created. + createObjects(occ); + } } } @@ -67,13 +82,25 @@ struct Manager sdbusplus::message::object_path o; msg.read(o); fs::path cpuPath(std::string(std::move(o))); - auto cpu = cpuPath.filename(); - std::string name{cpu.c_str()}; + auto name = cpuPath.filename().string(); auto index = name.find(CPU_NAME); name.replace(index, std::strlen(CPU_NAME), OCC_NAME); - auto path = fs::path(OCC_CONTROL_ROOT) / name; + createObjects(name); + + return 0; + } + + private: + /** @brief Create child OCC objects. + * + * @param[in] occ - the occ name, such as occ0. + */ + void createObjects(const std::string& occ) + { + auto path = fs::path(OCC_CONTROL_ROOT) / occ; + passThroughObjects.emplace_back( std::make_unique<PassThrough>( bus, @@ -86,16 +113,14 @@ struct Manager path.c_str())); // Create the power cap monitor object for master occ (0) - if(!pcap && (index == 0)) + if (!pcap) { pcap = std::make_unique<open_power::occ::powercap::PowerCap>( bus, - *statusObjects[index]); + *statusObjects.front()); } - return 0; } - private: /** @brief reference to the bus */ sdbusplus::bus::bus& bus; |