blob: 730467660a71cec90710b180213e1a79c3a88847 [file] [log] [blame]
Brad Bishopdd62e362017-06-14 16:54:03 -04001/**
2 * Copyright © 2017 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Matthew Barth2d2caa32020-05-26 11:07:24 -050016#include "tach.hpp"
17
Matt Spinlerc65d91d2021-04-21 13:09:49 -050018#include "logging.hpp"
Matthew Barth2d2caa32020-05-26 11:07:24 -050019#include "rpolicy.hpp"
20
Jay Meyerae226192020-10-15 15:33:17 -050021#include <fmt/format.h>
22
Brad Bishopd37c0f82017-07-28 21:47:00 -040023#include <phosphor-logging/log.hpp>
Matthew Barth2d2caa32020-05-26 11:07:24 -050024
Brad Bishopdd62e362017-06-14 16:54:03 -040025#include <string>
26#include <tuple>
27#include <vector>
Brad Bishopdd62e362017-06-14 16:54:03 -040028
29namespace phosphor
30{
31namespace fan
32{
33namespace presence
34{
35
Brad Bishopd37c0f82017-07-28 21:47:00 -040036using namespace phosphor::logging;
Brad Bishopdd62e362017-06-14 16:54:03 -040037using namespace std::literals::string_literals;
38
39static const auto tachNamespace = "/xyz/openbmc_project/sensors/fan_tach/"s;
40static const auto tachIface = "xyz.openbmc_project.Sensor.Value"s;
41static const auto tachProperty = "Value"s;
42
Matthew Barth2d2caa32020-05-26 11:07:24 -050043Tach::Tach(const std::vector<std::string>& sensors) : currentState(false)
Brad Bishopdd62e362017-06-14 16:54:03 -040044{
45 // Initialize state.
46 for (const auto& s : sensors)
47 {
48 state.emplace_back(s, nullptr, 0);
49 }
50}
51
52bool Tach::start()
53{
54 for (size_t i = 0; i < state.size(); ++i)
55 {
56 auto& s = state[i];
57 auto tachPath = tachNamespace + std::get<std::string>(s);
58
59 // Register for signal callbacks.
60 std::get<1>(s) = std::make_unique<sdbusplus::bus::match::match>(
Matthew Barth2d2caa32020-05-26 11:07:24 -050061 util::SDBusPlus::getBus(),
62 sdbusplus::bus::match::rules::propertiesChanged(tachPath,
63 tachIface),
64 [this, i](auto& msg) { this->propertiesChanged(i, msg); });
Brad Bishopdd62e362017-06-14 16:54:03 -040065
66 // Get an initial tach speed.
Brad Bishopd37c0f82017-07-28 21:47:00 -040067 try
68 {
Matthew Barthad2cd242020-08-13 13:36:19 -050069 std::get<double>(s) = util::SDBusPlus::getProperty<double>(
Matthew Barth2d2caa32020-05-26 11:07:24 -050070 tachPath, tachIface, tachProperty);
Brad Bishopd37c0f82017-07-28 21:47:00 -040071 }
72 catch (std::exception&)
73 {
74 // Assume not spinning.
75
Matthew Barthad2cd242020-08-13 13:36:19 -050076 std::get<double>(s) = 0;
Jay Meyerae226192020-10-15 15:33:17 -050077 log<level::INFO>(
78 fmt::format("Unable to read fan tach sensor {}", tachPath)
79 .c_str());
Brad Bishopd37c0f82017-07-28 21:47:00 -040080 }
Brad Bishopdd62e362017-06-14 16:54:03 -040081 }
82
83 // Set the initial state of the sensor.
Matthew Barth2d2caa32020-05-26 11:07:24 -050084 currentState = std::any_of(state.begin(), state.end(), [](const auto& s) {
Matthew Barthad2cd242020-08-13 13:36:19 -050085 return std::get<double>(s) != 0;
Matthew Barth2d2caa32020-05-26 11:07:24 -050086 });
Brad Bishopdd62e362017-06-14 16:54:03 -040087
88 return currentState;
89}
90
91void Tach::stop()
92{
93 for (auto& s : state)
94 {
95 // De-register signal callbacks.
96 std::get<1>(s) = nullptr;
97 }
98}
99
100bool Tach::present()
101{
102 // Live query the tach readings.
Matthew Barthad2cd242020-08-13 13:36:19 -0500103 std::vector<double> values;
Brad Bishopdd62e362017-06-14 16:54:03 -0400104 for (const auto& s : state)
105 {
Matthew Barthad2cd242020-08-13 13:36:19 -0500106 values.push_back(util::SDBusPlus::getProperty<double>(
Matthew Barth2d2caa32020-05-26 11:07:24 -0500107 tachNamespace + std::get<std::string>(s), tachIface, tachProperty));
Brad Bishopdd62e362017-06-14 16:54:03 -0400108 }
109
Matthew Barth2d2caa32020-05-26 11:07:24 -0500110 return std::any_of(values.begin(), values.end(),
111 [](const auto& v) { return v != 0; });
Brad Bishopdd62e362017-06-14 16:54:03 -0400112}
113
Matthew Barth2d2caa32020-05-26 11:07:24 -0500114void Tach::propertiesChanged(size_t sensor, sdbusplus::message::message& msg)
Brad Bishopdd62e362017-06-14 16:54:03 -0400115{
116 std::string iface;
Matthew Barthad2cd242020-08-13 13:36:19 -0500117 util::Properties<double> properties;
Brad Bishopdd62e362017-06-14 16:54:03 -0400118 msg.read(iface, properties);
119
120 propertiesChanged(sensor, properties);
121}
122
Matthew Barth2d2caa32020-05-26 11:07:24 -0500123void Tach::propertiesChanged(size_t sensor,
Matthew Barthad2cd242020-08-13 13:36:19 -0500124 const util::Properties<double>& props)
Brad Bishopdd62e362017-06-14 16:54:03 -0400125{
Brad Bishopdd62e362017-06-14 16:54:03 -0400126 // Find the Value property containing the speed.
127 auto it = props.find(tachProperty);
128 if (it != props.end())
129 {
Matthew Barth9f93bd32020-05-28 16:57:14 -0500130 auto& s = state[sensor];
Matthew Barthad2cd242020-08-13 13:36:19 -0500131 std::get<double>(s) = std::get<double>(it->second);
Brad Bishopdd62e362017-06-14 16:54:03 -0400132
Matthew Barth2d2caa32020-05-26 11:07:24 -0500133 auto newState =
Matthew Barthad2cd242020-08-13 13:36:19 -0500134 std::any_of(state.begin(), state.end(),
135 [](const auto& s) { return std::get<double>(s) != 0; });
Brad Bishopdd62e362017-06-14 16:54:03 -0400136
137 if (currentState != newState)
138 {
Brad Bishop11083ec2017-07-25 19:08:53 -0400139 getPolicy().stateChanged(newState, *this);
Brad Bishopdd62e362017-06-14 16:54:03 -0400140 currentState = newState;
141 }
142 }
143}
144
Matt Spinlerc65d91d2021-04-21 13:09:49 -0500145void Tach::logConflict(const std::string& fanInventoryPath) const
146{
147 getLogger().log(fmt::format(
148 "Tach sensor presence detect for fan {} said not present but "
149 "other methods indicated present",
150 fanInventoryPath));
151
152 // Let the code that monitors fan faults create the event
153 // logs for stopped rotors.
154}
155
Brad Bishopdd62e362017-06-14 16:54:03 -0400156} // namespace presence
157} // namespace fan
158} // namespace phosphor