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>
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 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 @@
          */
         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 @@
         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 @@
         /** @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