summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVishwanatha Subbanna <vishwa@linux.vnet.ibm.com>2017-08-10 18:25:26 +0530
committerVishwanatha Subbanna <vishwa@linux.vnet.ibm.com>2017-08-11 21:24:37 +0530
commit3e5422ed1a67bb37cd4dcb0159c803badf98c9fa (patch)
treee780d14efa28af451121c63a82a71c3c7368615d
parentd298105de8ff706e66fe9f45b034219988dd1473 (diff)
downloadopenpower-occ-control-3e5422ed1a67bb37cd4dcb0159c803badf98c9fa.zip
openpower-occ-control-3e5422ed1a67bb37cd4dcb0159c803badf98c9fa.tar.gz
Delay opening OCC device until bind
Fixes openbmc/openbmc#2118 Change-Id: If9e2610fe7443daa2196b0e5989f81bc544266b2 Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
-rw-r--r--configure.ac4
-rw-r--r--occ_pass_through.cpp54
-rw-r--r--occ_pass_through.hpp40
3 files changed, 80 insertions, 18 deletions
diff --git a/configure.ac b/configure.ac
index 098a0eb..24191c8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -101,6 +101,10 @@ AC_ARG_VAR(FSI_SCAN_FILE, [The File to write for initiating FSI rescan])
AS_IF([test "x$FSI_SCAN_FILE" == "x"], [FSI_SCAN_FILE="/sys/devices/platform/gpio-fsi/fsi0/slave@00:00/00:00:00:0a/fsi1/rescan"])
AC_DEFINE_UNQUOTED([FSI_SCAN_FILE], ["$FSI_SCAN_FILE"], [The File to write for initiating FSI rescan])
+AC_ARG_VAR(OCC_DEV_PATH, [The OCC device path in /dev])
+AS_IF([test "x$OCC_DEV_PATH" == "x"], [OCC_DEV_PATH="/dev/occ"])
+AC_DEFINE_UNQUOTED([OCC_DEV_PATH], ["$OCC_DEV_PATH"], [The OCC device path in /dev])
+
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])
diff --git a/occ_pass_through.cpp b/occ_pass_through.cpp
index 2846dda..4a7057b 100644
--- a/occ_pass_through.cpp
+++ b/occ_pass_through.cpp
@@ -2,11 +2,14 @@
#include <algorithm>
#include <fcntl.h>
#include <errno.h>
+#include <string>
+#include <unistd.h>
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/elog.hpp>
#include <org/open_power/OCC/Device/error.hpp>
#include "occ_pass_through.hpp"
#include "elog-errors.hpp"
+#include "config.h"
namespace open_power
{
namespace occ
@@ -17,20 +20,22 @@ PassThrough::PassThrough(
const char* path) :
Iface(bus, path),
path(path),
- fd(openDevice())
+ devicePath(OCC_DEV_PATH + std::to_string((this->path.back() - '0') + 1)),
+ activeStatusSignal(
+ bus,
+ sdbusRule::propertiesChanged(path, "org.open_power.OCC.Status"),
+ std::bind(std::mem_fn(&PassThrough::activeStatusEvent),
+ this, std::placeholders::_1))
{
// Nothing to do.
}
-int PassThrough::openDevice()
+void PassThrough::openDevice()
{
using namespace phosphor::logging;
using namespace sdbusplus::org::open_power::OCC::Device::Error;
- // Device instance number starts from 1.
- devicePath.append(std::to_string((this->path.back() - '0') + 1));
-
- int fd = open(devicePath.c_str(), O_RDWR | O_NONBLOCK);
+ fd = open(devicePath.c_str(), O_RDWR | O_NONBLOCK);
if (fd < 0)
{
// This would log and terminate since its not handled.
@@ -40,7 +45,15 @@ int PassThrough::openDevice()
phosphor::logging::org::open_power::OCC::Device::
OpenFailure::CALLOUT_DEVICE_PATH(devicePath.c_str()));
}
- return fd;
+ return;
+}
+
+void PassThrough::closeDevice()
+{
+ if (fd >= 0)
+ {
+ close(fd);
+ }
}
std::vector<int32_t> PassThrough::send(std::vector<int32_t> command)
@@ -60,7 +73,7 @@ std::vector<int32_t> PassThrough::send(std::vector<int32_t> command)
[](decltype(cmdInBytes)::value_type x){return x;});
ssize_t size = cmdInBytes.size() * sizeof(decltype(cmdInBytes)::value_type);
- auto rc = write((fd)(), cmdInBytes.data(), size);
+ auto rc = write(fd, cmdInBytes.data(), size);
if (rc < 0 || (rc != size))
{
// This would log and terminate since its not handled.
@@ -75,7 +88,7 @@ std::vector<int32_t> PassThrough::send(std::vector<int32_t> command)
while(1)
{
uint8_t data {};
- auto len = read((fd)(), &data, sizeof(data));
+ auto len = read(fd, &data, sizeof(data));
if (len > 0)
{
response.emplace_back(data);
@@ -105,5 +118,28 @@ std::vector<int32_t> PassThrough::send(std::vector<int32_t> command)
return response;
}
+// Called at OCC Status change signal
+void PassThrough::activeStatusEvent(sdbusplus::message::message& msg)
+{
+ std::string statusInterface;
+ std::map<std::string, sdbusplus::message::variant<bool>> msgData;
+ msg.read(statusInterface, msgData);
+
+ auto propertyMap = msgData.find("OccActive");
+ if (propertyMap != msgData.end())
+ {
+ // Extract the OccActive property
+ if (sdbusplus::message::variant_ns::get<bool>(propertyMap->second))
+ {
+ this->openDevice();
+ }
+ else
+ {
+ this->closeDevice();
+ }
+ }
+ return;
+}
+
} // namespace occ
} // namespace open_power
diff --git a/occ_pass_through.hpp b/occ_pass_through.hpp
index f2f78c7..205fc04 100644
--- a/occ_pass_through.hpp
+++ b/occ_pass_through.hpp
@@ -4,7 +4,6 @@
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server/object.hpp>
#include <org/open_power/OCC/PassThrough/server.hpp>
-#include "file.hpp"
namespace open_power
{
@@ -14,6 +13,9 @@ namespace occ
using Iface = sdbusplus::server::object::object<
sdbusplus::org::open_power::OCC::server::PassThrough>;
+// For waiting on signals
+namespace sdbusRule = sdbusplus::bus::match::rules;
+
/** @class PassThrough
* @brief Implements org.open_power.OCC.PassThrough
*/
@@ -21,7 +23,6 @@ class PassThrough : public Iface
{
public:
PassThrough() = delete;
- ~PassThrough() = default;
PassThrough(const PassThrough&) = delete;
PassThrough& operator=(const PassThrough&) = delete;
PassThrough(PassThrough&&) = default;
@@ -34,6 +35,11 @@ class PassThrough : public Iface
PassThrough(sdbusplus::bus::bus& bus,
const char* path);
+ ~PassThrough()
+ {
+ closeDevice();
+ }
+
/** @brief Pass through command to OCC
* @param[in] command - command to pass-through
* @returns OCC response as an array
@@ -48,17 +54,33 @@ class PassThrough : public Iface
/** @brief OCC device path
* For now, here is the hard-coded mapping until
* the udev rule is in.
- * occ0 --> /dev/occfifo1
- * occ1 --> /dev/occfifo2
+ * occ0 --> /dev/occ1
+ * occ1 --> /dev/occ2
* ...
*/
- std::string devicePath = "/dev/occ";
+ std::string devicePath;
- /** @brief File descriptor manager */
- FileDescriptor fd;
+ /** brief file descriptor associated with occ device */
+ int fd = -1;
+
+ /** @brief Subscribe to OCC Status signal
+ *
+ * Once the OCC status gets to active, only then we will get /dev/occ2
+ * populated and hence need to wait on that before opening that
+ */
+ sdbusplus::bus::match_t activeStatusSignal;
- /** Opens devicePath and returns file descritor */
- int openDevice();
+ /** Opens devicePath and populates file descritor */
+ void openDevice();
+
+ /** Closed the fd associated with opened device */
+ void closeDevice();
+
+ /** @brief Callback function on OCC Status change signals
+ *
+ * @param[in] msg - Data associated with subscribed signal
+ */
+ void activeStatusEvent(sdbusplus::message::message& msg);
};
} // namespace occ
OpenPOWER on IntegriCloud