summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--monitor/Makefile.am1
-rw-r--r--monitor/fan.cpp15
-rw-r--r--monitor/fan.hpp12
-rw-r--r--monitor/tach_sensor.cpp190
-rw-r--r--monitor/tach_sensor.hpp66
5 files changed, 283 insertions, 1 deletions
diff --git a/monitor/Makefile.am b/monitor/Makefile.am
index 26b66b5..6c6f4b3 100644
--- a/monitor/Makefile.am
+++ b/monitor/Makefile.am
@@ -11,6 +11,7 @@ phosphor_fan_monitor_SOURCES = \
tach_sensor.cpp
phosphor_fan_monitor_LDADD = \
+ $(top_builddir)/libfan.la \
$(SDBUSPLUS_LIBS) \
$(PHOSPHOR_LOGGING_LIBS)
diff --git a/monitor/fan.cpp b/monitor/fan.cpp
index b29eaab..852d2ba 100644
--- a/monitor/fan.cpp
+++ b/monitor/fan.cpp
@@ -51,6 +51,21 @@ Fan::Fan(sdbusplus::bus::bus& bus,
}
+void Fan::tachChanged()
+{
+ for (auto& s : _sensors)
+ {
+ tachChanged(*s);
+ }
+}
+
+
+void Fan::tachChanged(TachSensor& sensor)
+{
+ //TODO
+}
+
+
uint64_t Fan::getTargetSpeed(const TachSensor& sensor)
{
uint64_t target = 0;
diff --git a/monitor/fan.hpp b/monitor/fan.hpp
index 6cbd370..d79ae31 100644
--- a/monitor/fan.hpp
+++ b/monitor/fan.hpp
@@ -66,6 +66,18 @@ class Fan
std::shared_ptr<sd_event>& events,
const FanDefinition& def);
+ /**
+ * @brief Callback function for when an input sensor changes
+ *
+ * Starts a timer, where if it expires then the sensor
+ * was slow for too long and can be considered not functional.
+ */
+ void tachChanged(TachSensor& sensor);
+
+ /**
+ * @brief Calls tachChanged(sensor) on each sensor
+ */
+ void tachChanged();
private:
diff --git a/monitor/tach_sensor.cpp b/monitor/tach_sensor.cpp
index 3264ddf..c991bb6 100644
--- a/monitor/tach_sensor.cpp
+++ b/monitor/tach_sensor.cpp
@@ -25,7 +25,59 @@ namespace fan
namespace monitor
{
+constexpr auto PROPERTY_INTF = "org.freedesktop.DBus.Properties";
constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/";
+constexpr auto FAN_SENSOR_CONTROL_INTF = "xyz.openbmc_project.Control.FanSpeed";
+constexpr auto FAN_SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value";
+constexpr auto FAN_TARGET_PROPERTY = "Target";
+constexpr auto FAN_VALUE_PROPERTY = "Value";
+
+
+/**
+ * @brief Helper function to read a property
+ *
+ * @param[in] interface - the interface the property is on
+ * @param[in] propertName - the name of the property
+ * @param[in] path - the dbus path
+ * @param[in] service - the dbus service
+ * @param[in] bus - the dbus object
+ * @param[out] value - filled in with the property value
+ */
+template<typename T>
+static void readProperty(const std::string& interface,
+ const std::string& propertyName,
+ const std::string& path,
+ const std::string& service,
+ sdbusplus::bus::bus& bus,
+ T& value)
+{
+ sdbusplus::message::variant<T> property;
+
+ try
+ {
+ auto method = bus.new_method_call(service.c_str(),
+ path.c_str(),
+ PROPERTY_INTF,
+ "Get");
+
+ method.append(interface, propertyName);
+
+ auto reply = bus.call(method);
+ if (reply.is_method_error())
+ {
+ throw std::runtime_error(
+ "Error in property get call for path " +
+ path);
+ }
+
+ reply.read(property);
+ value = sdbusplus::message::variant_ns::get<T>(property);
+ }
+ catch (std::exception& e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
+ }
+}
TachSensor::TachSensor(sdbusplus::bus::bus& bus,
@@ -40,7 +92,143 @@ TachSensor::TachSensor(sdbusplus::bus::bus& bus,
_hasTarget(hasTarget),
_timeout(timeout)
{
- //TODO
+ auto service = getService();
+
+ //Load in starting Target and Input values
+ readProperty(FAN_SENSOR_VALUE_INTF,
+ FAN_VALUE_PROPERTY,
+ _name,
+ service,
+ _bus,
+ _tachInput);
+
+ if (_hasTarget)
+ {
+ readProperty(FAN_SENSOR_CONTROL_INTF,
+ FAN_TARGET_PROPERTY,
+ _name,
+ service,
+ _bus,
+ _tachTarget);
+ }
+
+ auto match = getMatchString(FAN_SENSOR_VALUE_INTF);
+
+ tachSignal = std::make_unique<sdbusplus::server::match::match>(
+ _bus,
+ match.c_str(),
+ handleTachChangeSignal,
+ this);
+
+ if (_hasTarget)
+ {
+ match = getMatchString(FAN_SENSOR_CONTROL_INTF);
+
+ targetSignal = std::make_unique<sdbusplus::server::match::match>(
+ _bus,
+ match.c_str(),
+ handleTargetChangeSignal,
+ this);
+ }
+
+}
+
+
+//Can cache this value after openbmc/openbmc#1496 is resolved
+std::string TachSensor::getService()
+{
+ return phosphor::fan::util::getService(_name,
+ FAN_SENSOR_CONTROL_INTF,
+ _bus);
+}
+
+
+std::string TachSensor::getMatchString(const std::string& interface)
+{
+ return std::string("type='signal',"
+ "interface='org.freedesktop.DBus.Properties',"
+ "member='PropertiesChanged',"
+ "arg0namespace='" + interface + "',"
+ "path='" + _name + "'");
+}
+
+
+int TachSensor::handleTachChangeSignal(sd_bus_message* msg,
+ void* usrData,
+ sd_bus_error* err)
+{
+ auto m = sdbusplus::message::message(msg);
+ static_cast<TachSensor*>(usrData)->handleTachChange(m, err);
+ return 0;
+}
+
+
+int TachSensor::handleTargetChangeSignal(sd_bus_message* msg,
+ void* usrData,
+ sd_bus_error* err)
+{
+ auto m = sdbusplus::message::message(msg);
+ static_cast<TachSensor*>(usrData)->handleTargetChange(m, err);
+ return 0;
+}
+
+
+/**
+ * @brief Reads a property from the input message and stores it in value.
+ * T is the value type.
+ *
+ * Note: This can only be called once per message.
+ *
+ * @param[in] msg - the dbus message that contains the data
+ * @param[in] interface - the interface the property is on
+ * @param[in] propertName - the name of the property
+ * @param[out] value - the value to store the property value in
+ */
+template<typename T>
+static void readPropertyFromMessage(sdbusplus::message::message& msg,
+ const std::string& interface,
+ const std::string& propertyName,
+ T& value)
+{
+ std::string sensor;
+ std::map<std::string, sdbusplus::message::variant<T>> data;
+ msg.read(sensor, data);
+
+ if (sensor.compare(interface) == 0)
+ {
+ auto propertyMap = data.find(propertyName);
+ if (propertyMap != data.end())
+ {
+ value = sdbusplus::message::variant_ns::get<T>(
+ propertyMap->second);
+ }
+ }
+}
+
+
+void TachSensor::handleTargetChange(sdbusplus::message::message& msg,
+ sd_bus_error* err)
+{
+ readPropertyFromMessage(msg,
+ FAN_SENSOR_CONTROL_INTF,
+ FAN_TARGET_PROPERTY,
+ _tachTarget);
+
+ //Check all tach sensors on the fan against the target
+ _fan.tachChanged();
+}
+
+
+void TachSensor::handleTachChange(sdbusplus::message::message& msg,
+ sd_bus_error* err)
+{
+ readPropertyFromMessage(msg,
+ FAN_SENSOR_VALUE_INTF,
+ FAN_VALUE_PROPERTY,
+ _tachInput);
+
+ //Check just this sensor against the target
+ _fan.tachChanged(*this);
}
diff --git a/monitor/tach_sensor.hpp b/monitor/tach_sensor.hpp
index df340f5..003763c 100644
--- a/monitor/tach_sensor.hpp
+++ b/monitor/tach_sensor.hpp
@@ -97,6 +97,62 @@ class TachSensor
private:
/**
+ * @brief Returns the service name for reading the sensor
+ */
+ std::string getService();
+
+ /**
+ * @brief Returns the match string to use for matching
+ * on a properties changed signal.
+ */
+ std::string getMatchString(const std::string& interface);
+
+ /**
+ * @brief Callback function for a tach input properties
+ * changed signal
+ *
+ * @param[in] msg - the dbus message
+ * @param[in] data - user data
+ * @param[in] err - dbus error
+ */
+ static int handleTachChangeSignal(sd_bus_message* msg,
+ void* data,
+ sd_bus_error* err);
+
+ /**
+ * @brief Callback function for a Target properties
+ * changed signal
+ *
+ * @param[in] msg - the dbus message
+ * @param[in] data - user data
+ * @param[in] err - dbus error
+ */
+ static int handleTargetChangeSignal(sd_bus_message* msg,
+ void* data,
+ sd_bus_error* err);
+
+ /**
+ * @brief Reads the Target property and stores in _tachTarget.
+ * Also calls Fan::tachChanged().
+ *
+ * @param[in] msg - the dbus message
+ * @param[in] err - dbus error
+ */
+ void handleTargetChange(sdbusplus::message::message& msg,
+ sd_bus_error* err);
+
+ /**
+ * @brief Reads the Value property and stores in _tachInput.
+ * Also calls Fan::tachChanged().
+ *
+ * @param[in] msg - the dbus message
+ * @param[in] err - dbus error
+ */
+ void handleTachChange(sdbusplus::message::message& msg,
+ sd_bus_error* err);
+
+
+ /**
* @brief the dbus object
*/
sdbusplus::bus::bus& _bus;
@@ -139,6 +195,16 @@ class TachSensor
* @brief The timeout value to use
*/
const size_t _timeout;
+
+ /**
+ * @brief The match object for the Value properties changed signal
+ */
+ std::unique_ptr<sdbusplus::server::match::match> tachSignal;
+
+ /**
+ * @brief The match object for the Target properties changed signal
+ */
+ std::unique_ptr<sdbusplus::server::match::match> targetSignal;
};
}
OpenPOWER on IntegriCloud