Add Support to do device bind and unbind based on OCC status
Fixes openbmc/openbmc#1698
Change-Id: Iaa33c3065b0358b62e3ec7e39d4b57c6b9d181e1
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index a15ea12..0ab5856 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,6 +7,7 @@
openpower_occ_control_SOURCES = \
occ_pass_through.cpp \
occ_status.cpp \
+ occ_device.cpp \
app.cpp \
org/open_power/OCC/PassThrough/error.cpp
diff --git a/configure.ac b/configure.ac
index 94673da..693c864 100644
--- a/configure.ac
+++ b/configure.ac
@@ -59,6 +59,10 @@
AS_IF([test "x$OCC_NAME" == "x"], [OCC_NAME="occ"])
AC_DEFINE_UNQUOTED([OCC_NAME], ["$OCC_NAME"], [The OCC object name])
+AC_ARG_VAR(OCC_HWMON_PATH, [The OCC hwmon path])
+AS_IF([test "x$OCC_HWMON_PATH" == "x"], [OCC_HWMON_PATH="/sys/bus/platform/drivers/occ-hwmon/"])
+AC_DEFINE_UNQUOTED([OCC_HWMON_PATH], ["$OCC_HWMON_PATH"], [The OCC hwmon path])
+
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
diff --git a/occ_device.cpp b/occ_device.cpp
new file mode 100644
index 0000000..865aef2
--- /dev/null
+++ b/occ_device.cpp
@@ -0,0 +1,12 @@
+#include "occ_device.hpp"
+
+namespace open_power
+{
+namespace occ
+{
+
+fs::path Device::bindPath = fs::path(OCC_HWMON_PATH) / "bind";
+fs::path Device::unBindPath = fs::path(OCC_HWMON_PATH) / "unbind";
+
+} // namespace occ
+} // namespace open_power
diff --git a/occ_device.hpp b/occ_device.hpp
new file mode 100644
index 0000000..dc057be
--- /dev/null
+++ b/occ_device.hpp
@@ -0,0 +1,79 @@
+#pragma once
+
+#include <fstream>
+#include <experimental/filesystem>
+#include "config.h"
+namespace open_power
+{
+namespace occ
+{
+
+namespace fs = std::experimental::filesystem;
+
+/** @class Device
+ * @brief Binds and unbinds the OCC driver upon request
+ */
+class Device
+{
+ public:
+ Device() = delete;
+ ~Device() = default;
+ Device(const Device&) = delete;
+ Device& operator=(const Device&) = delete;
+ Device(Device&&) = default;
+ Device& operator=(Device&&) = default;
+
+ /** @brief Constructs the Device object
+ *
+ * @param[in] name - OCC instance name
+ */
+ Device(const std::string& name) :
+ config(name + '-' + "dev0")
+ {
+ // Nothing to do here
+ }
+
+ /** @brief Binds device to the OCC driver */
+ inline void bind()
+ {
+ return write(bindPath, config);
+ }
+
+ /** @brief Un-binds device from the OCC driver */
+ inline void unBind()
+ {
+ return write(unBindPath, config);
+ }
+
+ private:
+ /** @brief Config value to be used to do bind and unbind */
+ const std::string config;
+
+ /** @brief To bind the device to the OCC driver, do:
+ * Write occ<#>-dev0 to: /sys/bus/platform/drivers/occ-hwmon/bind
+ */
+ static fs::path bindPath;
+
+ /** @brief To un-bind the device from the OCC driver, do:
+ * Write occ<#>-dev0 to: /sys/bus/platform/drivers/occ-hwmon/unbind
+ */
+ static fs::path unBindPath;
+
+ /** @brief file writer to achieve bind and unbind
+ *
+ * @param[in] filename - Name of file to be written
+ * @param[in] data - Data to be written to
+ * @return - None
+ */
+ void write(const fs::path& fileName, const std::string& data)
+ {
+ // If there is an error, move the exception all the way up
+ std::ofstream file(fileName, std::ios::out);
+ file << data;
+ file.close();
+ return;
+ }
+};
+
+} // namespace occ
+} // namespace open_power
diff --git a/occ_status.cpp b/occ_status.cpp
index a78ea47..ca8a1f9 100644
--- a/occ_status.cpp
+++ b/occ_status.cpp
@@ -7,6 +7,19 @@
// Handles updates to occActive property
bool Status::occActive(bool value)
{
+ if (value != this->occActive())
+ {
+ if (value)
+ {
+ // Bind the device
+ device.bind();
+ }
+ else
+ {
+ // Do the unbind
+ device.unBind();
+ }
+ }
return Base::Status::occActive(value);
}
diff --git a/occ_status.hpp b/occ_status.hpp
index 068f83b..5d092b7 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 "occ_device.hpp"
namespace open_power
{
namespace occ
@@ -30,11 +31,19 @@
* @param[in] path - DBus object path
*/
Status(sdbusplus::bus::bus& bus, const char* path)
- : Interface(bus, path)
+ : Interface(bus, path),
+ path(path),
+ device(name + std::to_string((this->path.back() - '0') + 1))
{
// Nothing to do here
}
+ /** @brief Since we are overriding the setter-occActive but not the
+ * getter-occActive, we need to have this using in order to
+ * allow passthrough usage of the getter-occActive
+ */
+ using Base::Status::occActive;
+
/** @brief SET OccActive to True or False
*
* @param[in] value - Intended value
@@ -42,6 +51,16 @@
* @return - Updated value of the property
*/
bool occActive(bool value) override;
+
+ private:
+ /** @brief OCC dbus object path */
+ std::string path;
+
+ /** @brief occ name prefix */
+ std::string name = OCC_NAME;
+
+ /** @brief OCC device object to do bind and unbind */
+ Device device;
};
} // namespace occ