summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVishwanatha Subbanna <vishwa@linux.vnet.ibm.com>2017-07-24 23:13:14 +0530
committerVishwanatha Subbanna <vishwa@linux.vnet.ibm.com>2017-08-02 22:52:49 +0530
commit30e329add77a72fffeb21e9d3203062a042c6f30 (patch)
treefda3abac4a04814232b8239afe26da21c65954b0
parent6add0b810bfd859ad21cb6b3f98b0bbfaa15aa62 (diff)
downloadopenpower-occ-control-30e329add77a72fffeb21e9d3203062a042c6f30.zip
openpower-occ-control-30e329add77a72fffeb21e9d3203062a042c6f30.tar.gz
Reset OCC on error condition
After detecting the error in the OCC, invokes OccReset command in Host Control dbus object with the sensor ID of the failing OCC Fixes openbmc/openbmc#1363 Change-Id: I608dbbb943d3b39d0709d6f350ab799e771a13e9 Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
-rw-r--r--Makefile.am6
-rw-r--r--occ_status.cpp60
-rw-r--r--occ_status.hpp42
-rw-r--r--test/Makefile.am1
-rw-r--r--utils.cpp53
-rw-r--r--utils.hpp23
6 files changed, 182 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am
index 548e7ff..aecbebb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,7 +5,8 @@ noinst_HEADERS = \
powercap.hpp \
occ_errors.hpp \
occ_events.hpp \
- occ_finder.hpp
+ occ_finder.hpp \
+ utils.hpp
sbin_PROGRAMS = openpower-occ-control
openpower_occ_control_SOURCES = \
@@ -16,7 +17,8 @@ openpower_occ_control_SOURCES = \
app.cpp \
powercap.cpp \
org/open_power/OCC/Device/error.cpp \
- occ_finder.cpp
+ occ_finder.cpp \
+ utils.cpp
BUILT_SOURCES = org/open_power/OCC/Device/error.hpp \
org/open_power/OCC/Device/error.cpp \
diff --git a/occ_status.cpp b/occ_status.cpp
index 08b1ef3..f740dc7 100644
--- a/occ_status.cpp
+++ b/occ_status.cpp
@@ -1,5 +1,7 @@
+#include <phosphor-logging/log.hpp>
#include "occ_status.hpp"
#include "occ_sensor.hpp"
+#include "utils.hpp"
namespace open_power
{
namespace occ
@@ -35,6 +37,64 @@ void Status::deviceErrorHandler()
{
// This would deem OCC inactive
this->occActive(false);
+
+ // Reset the OCC
+ this->resetOCC();
+}
+
+// Sends message to host control command handler to reset OCC
+void Status::resetOCC()
+{
+ using namespace phosphor::logging;
+ constexpr auto CONTROL_HOST_PATH = "/org/open_power/control/host0";
+ constexpr auto CONTROL_HOST_INTF = "org.open_power.Control.Host";
+
+ // This will throw exception on failure
+ auto service = getService(bus, CONTROL_HOST_PATH, CONTROL_HOST_INTF);
+
+ auto method = bus.new_method_call(service.c_str(),
+ CONTROL_HOST_PATH,
+ CONTROL_HOST_INTF,
+ "Execute");
+ // OCC Reset control command
+ method.append(convertForMessage(
+ Control::Host::Command::OCCReset).c_str());
+
+ // OCC Sensor ID for callout reasons
+ method.append(sdbusplus::message::variant<uint8_t>(
+ sensorMap.at(instance)));
+ bus.call_noreply(method);
+ return;
+}
+
+// Handler called by Host control command handler to convey the
+// status of the executed command
+void Status::hostControlEvent(sdbusplus::message::message& msg)
+{
+ using namespace phosphor::logging;
+
+ std::string cmdCompleted{};
+ std::string cmdStatus{};
+
+ msg.read(cmdCompleted, cmdStatus);
+
+ log<level::DEBUG>("Host control signal values",
+ entry("COMMAND=%s",cmdCompleted.c_str()),
+ entry("STATUS=%s",cmdStatus.c_str()));
+
+ if(Control::Host::convertResultFromString(cmdStatus) !=
+ Control::Host::Result::Success)
+ {
+ if(Control::Host::convertCommandFromString(cmdCompleted) ==
+ Control::Host::Command::OCCReset)
+ {
+ // Must be a Timeout. Log an Erorr trace
+ log<level::ERR>("Error resetting the OCC.",
+ entry("PATH=%s", path.c_str()),
+ entry("SensorID=0x%X",sensorMap.at(instance)));
+ }
+ }
+ return;
}
} // namespace occ
diff --git a/occ_status.hpp b/occ_status.hpp
index d30d642..e07ca61 100644
--- a/occ_status.hpp
+++ b/occ_status.hpp
@@ -3,6 +3,7 @@
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server/object.hpp>
#include <org/open_power/OCC/Status/server.hpp>
+#include <org/open_power/Control/Host/server.hpp>
#include "occ_events.hpp"
#include "occ_device.hpp"
namespace open_power
@@ -13,6 +14,12 @@ namespace occ
namespace Base = sdbusplus::org::open_power::OCC::server;
using Interface = sdbusplus::server::object::object<Base::Status>;
+// IPMID's host control application
+namespace Control = sdbusplus::org::open_power::Control::server;
+
+// For waiting on signals
+namespace sdbusRule = sdbusplus::bus::match::rules;
+
// OCC status instance. Ex. for "occ0", the instance is 0
using instanceID = int;
@@ -40,11 +47,22 @@ class Status : public Interface
*/
Status(sdbusplus::bus::bus& bus, EventPtr& event, const char* path)
: Interface(bus, path),
+ bus(bus),
path(path),
instance(((this->path.back() - '0'))),
device(event,
name + std::to_string(instance + 1),
- std::bind(&Status::deviceErrorHandler, this))
+ std::bind(&Status::deviceErrorHandler, this)),
+ hostControlSignal(
+ bus,
+ sdbusRule::type::signal() +
+ sdbusRule::member("CommandComplete") +
+ sdbusRule::path("/org/open_power/control/host0") +
+ sdbusRule::interface("org.open_power.Control.Host") +
+ sdbusRule::argN(0, Control::convertForMessage(
+ Control::Host::Command::OCCReset)),
+ std::bind(std::mem_fn(&Status::hostControlEvent),
+ this, std::placeholders::_1))
{
// Nothing to do here
}
@@ -64,6 +82,10 @@ class Status : public Interface
bool occActive(bool value) override;
private:
+
+ /** @brief sdbus handle */
+ sdbusplus::bus::bus& bus;
+
/** @brief OCC dbus object path */
std::string path;
@@ -79,8 +101,26 @@ class Status : public Interface
/** @brief OCC device object to do bind and unbind */
Device device;
+ /** @brief Subscribe to host control signal
+ *
+ * Once the OCC reset is requested, BMC sends that message to host.
+ * If the host does not ack the message, then there would be a timeout
+ * and we need to catch that to log an error
+ **/
+ sdbusplus::bus::match_t hostControlSignal;
+
/** @brief Callback handler when device errors are detected */
void deviceErrorHandler();
+
+ /** @brief Callback function on host control signals
+ *
+ * @param[in] msg - Data associated with subscribed signal
+ */
+ void hostControlEvent(sdbusplus::message::message& msg);
+
+ /** @brief Sends a message to host control command handler to reset OCC
+ */
+ void resetOCC();
};
} // namespace occ
diff --git a/test/Makefile.am b/test/Makefile.am
index a680245..d644de8 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -20,4 +20,5 @@ utest_LDADD = $(top_builddir)/powercap.o \
$(top_builddir)/occ_status.o \
$(top_builddir)/occ_device.o \
$(top_builddir)/occ_errors.o \
+ $(top_builddir)/utils.o \
$(top_builddir)/org/open_power/OCC/Device/error.o
diff --git a/utils.cpp b/utils.cpp
new file mode 100644
index 0000000..1dfdcef
--- /dev/null
+++ b/utils.cpp
@@ -0,0 +1,53 @@
+#include <string>
+#include <sdbusplus/bus.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+#include <xyz/openbmc_project/Common/error.hpp>
+namespace open_power
+{
+namespace occ
+{
+
+// For throwing exceptions
+using namespace phosphor::logging;
+using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
+ Error::InternalFailure;
+
+std::string getService(sdbusplus::bus::bus& bus,
+ const std::string& intf,
+ const std::string& path)
+{
+ auto mapperCall = bus.new_method_call("xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper",
+ "GetObject");
+
+ mapperCall.append(path);
+ mapperCall.append(std::vector<std::string>({intf}));
+
+ auto mapperResponseMsg = bus.call(mapperCall);
+
+ if (mapperResponseMsg.is_method_error())
+ {
+ log<level::ERR>("ERROR in getting service",
+ entry("PATH=%s",path.c_str()),
+ entry("INTERFACE=%s",intf.c_str()));
+
+ elog<InternalFailure>();
+ }
+
+ std::map<std::string, std::vector<std::string>> mapperResponse;
+ mapperResponseMsg.read(mapperResponse);
+
+ if (mapperResponse.begin() == mapperResponse.end())
+ {
+ log<level::ERR>("ERROR reading mapper response",
+ entry("PATH=%s",path.c_str()),
+ entry("INTERFACE=%s",intf.c_str()));
+
+ elog<InternalFailure>();
+ }
+ return mapperResponse.begin()->first;
+}
+
+} // namespace occ
+} // namespace open_power
diff --git a/utils.hpp b/utils.hpp
new file mode 100644
index 0000000..51f9832
--- /dev/null
+++ b/utils.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <sdbusplus/bus.hpp>
+#include <string>
+namespace open_power
+{
+namespace occ
+{
+/**
+ * @brief Gets the D-Bus Service name for the input D-Bus path
+ *
+ * @param[in] bus - Bus handler
+ * @param[in] intf - Interface
+ * @param[in] path - Object Path
+ *
+ * @return Service name
+ * @error InternalFailure exception thrown
+ */
+std::string getService(sdbusplus::bus::bus& bus,
+ const std::string& intf,
+ const std::string& path);
+} // namespace occ
+} // namespace open_power
OpenPOWER on IntegriCloud