blob: d27c3566b0ef1333c9bc28fc485716511c240529 [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
Anwaar Hadiebead9a2025-03-19 20:35:57 +000021#include <phosphor-logging/lg2.hpp>
Matthew Barth2d2caa32020-05-26 11:07:24 -050022
Patrick Williamsfbf47032023-07-17 12:27:34 -050023#include <format>
Brad Bishopdd62e362017-06-14 16:54:03 -040024#include <string>
25#include <tuple>
26#include <vector>
Brad Bishopdd62e362017-06-14 16:54:03 -040027
28namespace phosphor
29{
30namespace fan
31{
32namespace presence
33{
34
Brad Bishopd37c0f82017-07-28 21:47:00 -040035using namespace phosphor::logging;
Brad Bishopdd62e362017-06-14 16:54:03 -040036using namespace std::literals::string_literals;
37
38static const auto tachNamespace = "/xyz/openbmc_project/sensors/fan_tach/"s;
39static const auto tachIface = "xyz.openbmc_project.Sensor.Value"s;
40static const auto tachProperty = "Value"s;
41
Matthew Barth2d2caa32020-05-26 11:07:24 -050042Tach::Tach(const std::vector<std::string>& sensors) : currentState(false)
Brad Bishopdd62e362017-06-14 16:54:03 -040043{
44 // Initialize state.
45 for (const auto& s : sensors)
46 {
47 state.emplace_back(s, nullptr, 0);
48 }
49}
50
51bool Tach::start()
52{
53 for (size_t i = 0; i < state.size(); ++i)
54 {
55 auto& s = state[i];
56 auto tachPath = tachNamespace + std::get<std::string>(s);
57
58 // Register for signal callbacks.
Patrick Williamscb356d42022-07-22 19:26:53 -050059 std::get<1>(s) = std::make_unique<sdbusplus::bus::match_t>(
Matthew Barth2d2caa32020-05-26 11:07:24 -050060 util::SDBusPlus::getBus(),
61 sdbusplus::bus::match::rules::propertiesChanged(tachPath,
62 tachIface),
63 [this, i](auto& msg) { this->propertiesChanged(i, msg); });
Brad Bishopdd62e362017-06-14 16:54:03 -040064
65 // Get an initial tach speed.
Brad Bishopd37c0f82017-07-28 21:47:00 -040066 try
67 {
Matthew Barthad2cd242020-08-13 13:36:19 -050068 std::get<double>(s) = util::SDBusPlus::getProperty<double>(
Matthew Barth2d2caa32020-05-26 11:07:24 -050069 tachPath, tachIface, tachProperty);
Brad Bishopd37c0f82017-07-28 21:47:00 -040070 }
Patrick Williamsddb773b2021-10-06 11:24:49 -050071 catch (const std::exception&)
Brad Bishopd37c0f82017-07-28 21:47:00 -040072 {
73 // Assume not spinning.
74
Matthew Barthad2cd242020-08-13 13:36:19 -050075 std::get<double>(s) = 0;
Anwaar Hadiebead9a2025-03-19 20:35:57 +000076 lg2::info("Unable to read fan tach sensor {TACPATH}", "TACPATH",
77 tachPath);
Brad Bishopd37c0f82017-07-28 21:47:00 -040078 }
Brad Bishopdd62e362017-06-14 16:54:03 -040079 }
80
81 // Set the initial state of the sensor.
Matthew Barth2d2caa32020-05-26 11:07:24 -050082 currentState = std::any_of(state.begin(), state.end(), [](const auto& s) {
Matthew Barthad2cd242020-08-13 13:36:19 -050083 return std::get<double>(s) != 0;
Matthew Barth2d2caa32020-05-26 11:07:24 -050084 });
Brad Bishopdd62e362017-06-14 16:54:03 -040085
86 return currentState;
87}
88
89void Tach::stop()
90{
91 for (auto& s : state)
92 {
93 // De-register signal callbacks.
94 std::get<1>(s) = nullptr;
95 }
96}
97
98bool Tach::present()
99{
100 // Live query the tach readings.
Matthew Barthad2cd242020-08-13 13:36:19 -0500101 std::vector<double> values;
Brad Bishopdd62e362017-06-14 16:54:03 -0400102 for (const auto& s : state)
103 {
Matthew Barthad2cd242020-08-13 13:36:19 -0500104 values.push_back(util::SDBusPlus::getProperty<double>(
Matthew Barth2d2caa32020-05-26 11:07:24 -0500105 tachNamespace + std::get<std::string>(s), tachIface, tachProperty));
Brad Bishopdd62e362017-06-14 16:54:03 -0400106 }
107
Matthew Barth2d2caa32020-05-26 11:07:24 -0500108 return std::any_of(values.begin(), values.end(),
109 [](const auto& v) { return v != 0; });
Brad Bishopdd62e362017-06-14 16:54:03 -0400110}
111
Patrick Williamscb356d42022-07-22 19:26:53 -0500112void Tach::propertiesChanged(size_t sensor, sdbusplus::message_t& msg)
Brad Bishopdd62e362017-06-14 16:54:03 -0400113{
114 std::string iface;
Matthew Barthad2cd242020-08-13 13:36:19 -0500115 util::Properties<double> properties;
Brad Bishopdd62e362017-06-14 16:54:03 -0400116 msg.read(iface, properties);
117
118 propertiesChanged(sensor, properties);
119}
120
Matthew Barth2d2caa32020-05-26 11:07:24 -0500121void Tach::propertiesChanged(size_t sensor,
Matthew Barthad2cd242020-08-13 13:36:19 -0500122 const util::Properties<double>& props)
Brad Bishopdd62e362017-06-14 16:54:03 -0400123{
Brad Bishopdd62e362017-06-14 16:54:03 -0400124 // Find the Value property containing the speed.
125 auto it = props.find(tachProperty);
126 if (it != props.end())
127 {
Matthew Barth9f93bd32020-05-28 16:57:14 -0500128 auto& s = state[sensor];
Matthew Barthad2cd242020-08-13 13:36:19 -0500129 std::get<double>(s) = std::get<double>(it->second);
Brad Bishopdd62e362017-06-14 16:54:03 -0400130
Matthew Barth2d2caa32020-05-26 11:07:24 -0500131 auto newState =
Matthew Barthad2cd242020-08-13 13:36:19 -0500132 std::any_of(state.begin(), state.end(),
133 [](const auto& s) { return std::get<double>(s) != 0; });
Brad Bishopdd62e362017-06-14 16:54:03 -0400134
135 if (currentState != newState)
136 {
Brad Bishop11083ec2017-07-25 19:08:53 -0400137 getPolicy().stateChanged(newState, *this);
Brad Bishopdd62e362017-06-14 16:54:03 -0400138 currentState = newState;
139 }
140 }
141}
142
Matt Spinlerc65d91d2021-04-21 13:09:49 -0500143void Tach::logConflict(const std::string& fanInventoryPath) const
144{
Patrick Williamsfbf47032023-07-17 12:27:34 -0500145 getLogger().log(std::format(
Matt Spinlerc65d91d2021-04-21 13:09:49 -0500146 "Tach sensor presence detect for fan {} said not present but "
147 "other methods indicated present",
148 fanInventoryPath));
149
150 // Let the code that monitors fan faults create the event
151 // logs for stopped rotors.
152}
153
Brad Bishopdd62e362017-06-14 16:54:03 -0400154} // namespace presence
155} // namespace fan
156} // namespace phosphor