summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepak Kodihalli <dkodihal@in.ibm.com>2017-07-26 08:25:59 -0500
committerDeepak Kodihalli <dkodihal@in.ibm.com>2017-08-01 10:55:50 -0500
commit5f031f3c722f0a4d10e562f5cfa54ba32d12958e (patch)
tree50516eb3c732e38d78cbb49528b5d9800b06da9c
parentee4d83dfc7b6cf3b5979541ab5b1918b68e6bbdb (diff)
downloadopenpower-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.am6
-rw-r--r--configure.ac4
-rw-r--r--occ_finder.cpp82
-rw-r--r--occ_finder.hpp20
-rw-r--r--occ_manager.hpp57
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;
OpenPOWER on IntegriCloud