blob: 98562425a139c042546ecadf7847d1aa8f64ebcf [file] [log] [blame]
Matt Spinlerabf8da32017-04-27 14:08:45 -05001/**
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 */
Matt Spinlerabf8da32017-04-27 14:08:45 -050016#include "fan.hpp"
Matthew Barth177fe982020-05-26 11:05:19 -050017
Matt Spinlerae1f8ef2020-10-14 16:15:51 -050018#include "logging.hpp"
Matthew Barth177fe982020-05-26 11:05:19 -050019#include "sdbusplus.hpp"
Matt Spinlerb0412d02020-10-12 16:53:52 -050020#include "system.hpp"
Matt Spinlerabf8da32017-04-27 14:08:45 -050021#include "types.hpp"
Matt Spinlerb1e18512017-04-27 14:42:33 -050022#include "utility.hpp"
Matthew Barth177fe982020-05-26 11:05:19 -050023
Jay Meyera7aed012020-10-06 14:32:22 -050024#include <fmt/format.h>
25
Matthew Barth177fe982020-05-26 11:05:19 -050026#include <phosphor-logging/log.hpp>
27
28#include <algorithm>
Matt Spinlerabf8da32017-04-27 14:08:45 -050029
30namespace phosphor
31{
32namespace fan
33{
34namespace monitor
35{
36
37using namespace phosphor::logging;
Matt Spinlerb0412d02020-10-12 16:53:52 -050038using namespace sdbusplus::bus::match;
Matt Spinlerabf8da32017-04-27 14:08:45 -050039
Matthew Barth177fe982020-05-26 11:05:19 -050040Fan::Fan(Mode mode, sdbusplus::bus::bus& bus, const sdeventplus::Event& event,
Matt Spinlerb0412d02020-10-12 16:53:52 -050041 std::unique_ptr<trust::Manager>& trust, const FanDefinition& def,
42 System& system) :
Matt Spinlerabf8da32017-04-27 14:08:45 -050043 _bus(bus),
44 _name(std::get<fanNameField>(def)),
45 _deviation(std::get<fanDeviationField>(def)),
Matt Spinlerc39e8592017-09-28 13:13:08 -050046 _numSensorFailsForNonFunc(std::get<numSensorFailsForNonfuncField>(def)),
Matt Spinlerb0412d02020-10-12 16:53:52 -050047 _trustManager(trust),
48#ifdef MONITOR_USE_JSON
49 _monitorDelay(std::get<monitorStartDelayField>(def)),
50 _monitorTimer(event, std::bind(std::mem_fn(&Fan::startMonitor), this)),
51#endif
Matt Spinlerb63aa092020-10-14 09:45:11 -050052 _system(system),
53 _presenceMatch(bus,
54 rules::propertiesChanged(util::INVENTORY_PATH + _name,
55 util::INV_ITEM_IFACE),
56 std::bind(std::mem_fn(&Fan::presenceChanged), this,
Matt Spinler27f6b682020-10-27 08:43:37 -050057 std::placeholders::_1)),
Matt Spinler7d135642021-02-04 12:44:17 -060058 _presenceIfaceAddedMatch(
59 bus,
60 rules::interfacesAdded() +
61 rules::argNpath(0, util::INVENTORY_PATH + _name),
62 std::bind(std::mem_fn(&Fan::presenceIfaceAdded), this,
63 std::placeholders::_1)),
Matt Spinler623635c2021-03-29 13:13:59 -050064 _fanMissingErrorDelay(std::get<fanMissingErrDelayField>(def)),
Matt Spinlera3584bd2021-03-29 15:48:30 -050065 _setFuncOnPresent(std::get<funcOnPresentField>(def))
Matt Spinlerabf8da32017-04-27 14:08:45 -050066{
Matthew Barth0a9fe162018-01-26 12:53:15 -060067 // Setup tach sensors for monitoring
68 auto& sensors = std::get<sensorListField>(def);
69 for (auto& s : sensors)
70 {
Matt Spinler4283c5d2021-03-01 15:56:00 -060071 _sensors.emplace_back(std::make_shared<TachSensor>(
72 mode, bus, *this, std::get<sensorNameField>(s),
73 std::get<hasTargetField>(s), std::get<funcDelay>(def),
74 std::get<targetInterfaceField>(s), std::get<factorField>(s),
75 std::get<offsetField>(s), std::get<methodField>(def),
Matthew Barth8a8aa442021-11-19 14:13:13 -060076 std::get<thresholdField>(s), std::get<ignoreAboveMaxField>(s),
77 std::get<timeoutField>(def),
Matt Spinlerfdfcc672021-06-01 14:51:06 -060078 std::get<nonfuncRotorErrDelayField>(def),
79 std::get<countIntervalField>(def), event));
Matthew Barth0a9fe162018-01-26 12:53:15 -060080
Matt Spinler4283c5d2021-03-01 15:56:00 -060081 _trustManager->registerSensor(_sensors.back());
Matthew Barth0a9fe162018-01-26 12:53:15 -060082 }
83
Mike Cappsce6820a2021-05-26 10:40:19 -040084 bool functionalState =
85 (_numSensorFailsForNonFunc == 0) ||
86 (countNonFunctionalSensors() < _numSensorFailsForNonFunc);
87
Mike Capps9ff48772021-07-19 14:49:43 -040088 if (updateInventory(functionalState) && !functionalState)
89 {
90 // the inventory update threw an exception, possibly because D-Bus
91 // wasn't ready. Try to update sensors back to functional to avoid a
92 // false-alarm. They will be updated again from subscribing to the
93 // properties-changed event
94
95 for (auto& sensor : _sensors)
96 sensor->setFunctional(true);
97 }
Mike Cappsce6820a2021-05-26 10:40:19 -040098
Matt Spinlerb0412d02020-10-12 16:53:52 -050099#ifndef MONITOR_USE_JSON
Matthew Barth0a9fe162018-01-26 12:53:15 -0600100 // Check current tach state when entering monitor mode
Matthew Barth6ad28432017-08-22 11:18:19 -0500101 if (mode != Mode::init)
102 {
Matt Spinlerb0412d02020-10-12 16:53:52 -0500103 _monitorReady = true;
104
Matthew Barth177fe982020-05-26 11:05:19 -0500105 // The TachSensors will now have already read the input
106 // and target values, so check them.
Matthew Barth6ad28432017-08-22 11:18:19 -0500107 tachChanged();
108 }
Matt Spinlerb0412d02020-10-12 16:53:52 -0500109#else
Matt Spinler7d135642021-02-04 12:44:17 -0600110 if (_system.isPowerOn())
111 {
112 _monitorTimer.restartOnce(std::chrono::seconds(_monitorDelay));
113 }
Matt Spinlerb0412d02020-10-12 16:53:52 -0500114#endif
Matt Spinlerb63aa092020-10-14 09:45:11 -0500115
Matt Spinler27f6b682020-10-27 08:43:37 -0500116 if (_fanMissingErrorDelay)
117 {
118 _fanMissingErrorTimer = std::make_unique<
119 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
120 event, std::bind(&System::fanMissingErrorTimerExpired, &system,
121 std::ref(*this)));
Matt Spinler7d135642021-02-04 12:44:17 -0600122 }
Matt Spinler27f6b682020-10-27 08:43:37 -0500123
Matt Spinler7d135642021-02-04 12:44:17 -0600124 try
125 {
126 _present = util::SDBusPlus::getProperty<bool>(
127 util::INVENTORY_PATH + _name, util::INV_ITEM_IFACE, "Present");
128
129 if (!_present)
Matt Spinler27f6b682020-10-27 08:43:37 -0500130 {
Matt Spinlerac372972021-01-25 15:11:22 -0600131 getLogger().log(
132 fmt::format("On startup, fan {} is missing", _name));
Matt Spinler7d135642021-02-04 12:44:17 -0600133 if (_system.isPowerOn() && _fanMissingErrorTimer)
134 {
135 _fanMissingErrorTimer->restartOnce(
136 std::chrono::seconds{*_fanMissingErrorDelay});
137 }
138 }
139 }
140 catch (const util::DBusServiceError& e)
141 {
142 // This could happen on the first BMC boot if the presence
143 // detect app hasn't started yet and there isn't an inventory
144 // cache yet.
145 }
146}
147
148void Fan::presenceIfaceAdded(sdbusplus::message::message& msg)
149{
150 sdbusplus::message::object_path path;
151 std::map<std::string, std::map<std::string, std::variant<bool>>> interfaces;
152
153 msg.read(path, interfaces);
154
155 auto properties = interfaces.find(util::INV_ITEM_IFACE);
156 if (properties == interfaces.end())
157 {
158 return;
159 }
160
161 auto property = properties->second.find("Present");
162 if (property == properties->second.end())
163 {
164 return;
165 }
166
167 _present = std::get<bool>(property->second);
168
169 if (!_present)
170 {
171 getLogger().log(fmt::format(
172 "New fan {} interface added and fan is not present", _name));
173 if (_system.isPowerOn() && _fanMissingErrorTimer)
174 {
Matt Spinler27f6b682020-10-27 08:43:37 -0500175 _fanMissingErrorTimer->restartOnce(
176 std::chrono::seconds{*_fanMissingErrorDelay});
177 }
178 }
Matt Spinler7d135642021-02-04 12:44:17 -0600179
180 _system.fanStatusChange(*this);
Matt Spinlerb0412d02020-10-12 16:53:52 -0500181}
182
183void Fan::startMonitor()
184{
185 _monitorReady = true;
186
Matt Spinler4283c5d2021-03-01 15:56:00 -0600187 std::for_each(_sensors.begin(), _sensors.end(), [this](auto& sensor) {
188 if (_present)
189 {
190 try
191 {
192 // Force a getProperty call to check if the tach sensor is
193 // on D-Bus. If it isn't, now set it to nonfunctional.
194 // This isn't done earlier so that code watching for
195 // nonfunctional tach sensors doesn't take actions before
196 // those sensors show up on D-Bus.
197 sensor->updateTachAndTarget();
198 tachChanged(*sensor);
199 }
200 catch (const util::DBusServiceError& e)
201 {
202 // The tach property still isn't on D-Bus, ensure
203 // sensor is nonfunctional.
204 getLogger().log(fmt::format(
205 "Monitoring starting but {} sensor value not on D-Bus",
206 sensor->name()));
207
208 sensor->setFunctional(false);
209
210 if (_numSensorFailsForNonFunc)
211 {
212 if (_functional && (countNonFunctionalSensors() >=
213 _numSensorFailsForNonFunc))
214 {
215 updateInventory(false);
216 }
217 }
218
219 _system.fanStatusChange(*this);
220 }
221 }
222 });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500223}
224
Matt Spinlerebaae612017-04-27 14:21:48 -0500225void Fan::tachChanged()
226{
Matt Spinlerb0412d02020-10-12 16:53:52 -0500227 if (_monitorReady)
Matt Spinlerebaae612017-04-27 14:21:48 -0500228 {
Matt Spinlerb0412d02020-10-12 16:53:52 -0500229 for (auto& s : _sensors)
230 {
231 tachChanged(*s);
232 }
Matt Spinlerebaae612017-04-27 14:21:48 -0500233 }
234}
235
Matt Spinlerebaae612017-04-27 14:21:48 -0500236void Fan::tachChanged(TachSensor& sensor)
237{
Matt Spinler7d135642021-02-04 12:44:17 -0600238 if (!_system.isPowerOn() || !_monitorReady)
239 {
240 return;
241 }
242
Matt Spinlerc39e8592017-09-28 13:13:08 -0500243 if (_trustManager->active())
244 {
245 if (!_trustManager->checkTrust(sensor))
246 {
247 return;
248 }
249 }
250
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600251 // If the error checking method is 'count', if a tach change leads
252 // to an out of range sensor the count timer will take over in calling
253 // process() until the sensor is healthy again.
254 if (!sensor.countTimerRunning())
Matt Spinler623635c2021-03-29 13:13:59 -0500255 {
256 process(sensor);
257 }
258}
259
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600260void Fan::countTimerExpired(TachSensor& sensor)
Matt Spinler623635c2021-03-29 13:13:59 -0500261{
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600262 if (_trustManager->active() && !_trustManager->checkTrust(sensor))
Matt Spinler623635c2021-03-29 13:13:59 -0500263 {
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600264 return;
Matt Spinler623635c2021-03-29 13:13:59 -0500265 }
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600266 process(sensor);
Matthew Barthfcb0dbc2021-02-10 14:23:39 -0600267}
268
269void Fan::process(TachSensor& sensor)
270{
Matthew Barth177fe982020-05-26 11:05:19 -0500271 // If this sensor is out of range at this moment, start
272 // its timer, at the end of which the inventory
273 // for the fan may get updated to not functional.
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500274
Matthew Barth177fe982020-05-26 11:05:19 -0500275 // If this sensor is OK, put everything back into a good state.
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500276
277 if (outOfRange(sensor))
278 {
Matthew Barthe11cbc62018-02-20 12:11:07 -0600279 if (sensor.functional())
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500280 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800281 switch (sensor.getMethod())
282 {
283 case MethodMode::timebased:
284 // Start nonfunctional timer if not already running
285 sensor.startTimer(TimerMode::nonfunc);
286 break;
287 case MethodMode::count:
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600288
289 if (!sensor.countTimerRunning())
290 {
291 sensor.startCountTimer();
292 }
Jolie Ku69f2f482020-10-21 09:59:43 +0800293 sensor.setCounter(true);
294 if (sensor.getCounter() >= sensor.getThreshold())
295 {
296 updateState(sensor);
297 }
298 break;
299 }
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500300 }
301 }
302 else
303 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800304 switch (sensor.getMethod())
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500305 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800306 case MethodMode::timebased:
307 if (sensor.functional())
308 {
Matthew Barth11b5d8f2021-01-28 14:04:09 -0600309 if (sensor.timerRunning())
310 {
311 sensor.stopTimer();
312 }
Jolie Ku69f2f482020-10-21 09:59:43 +0800313 }
314 else
315 {
316 // Start functional timer if not already running
317 sensor.startTimer(TimerMode::func);
318 }
319 break;
320 case MethodMode::count:
321 sensor.setCounter(false);
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600322 if (sensor.getCounter() == 0)
Jolie Ku69f2f482020-10-21 09:59:43 +0800323 {
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600324 if (!sensor.functional())
325 {
326 updateState(sensor);
327 }
328
329 sensor.stopCountTimer();
Jolie Ku69f2f482020-10-21 09:59:43 +0800330 }
331 break;
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500332 }
333 }
Matt Spinlerebaae612017-04-27 14:21:48 -0500334}
335
Matthew Barthf552ea52018-01-15 16:22:04 -0600336uint64_t Fan::findTargetSpeed()
Matt Spinlerabf8da32017-04-27 14:08:45 -0500337{
338 uint64_t target = 0;
Matthew Barth177fe982020-05-26 11:05:19 -0500339 // The sensor doesn't support a target,
340 // so get it from another sensor.
Matthew Barthf552ea52018-01-15 16:22:04 -0600341 auto s = std::find_if(_sensors.begin(), _sensors.end(),
Matthew Barth177fe982020-05-26 11:05:19 -0500342 [](const auto& s) { return s->hasTarget(); });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500343
Matthew Barthf552ea52018-01-15 16:22:04 -0600344 if (s != _sensors.end())
Matt Spinlerabf8da32017-04-27 14:08:45 -0500345 {
Matthew Barthf552ea52018-01-15 16:22:04 -0600346 target = (*s)->getTarget();
Matt Spinlerabf8da32017-04-27 14:08:45 -0500347 }
348
349 return target;
350}
351
Mike Cappsce6820a2021-05-26 10:40:19 -0400352size_t Fan::countNonFunctionalSensors() const
Matt Spinlerabf8da32017-04-27 14:08:45 -0500353{
Matthew Barth7c23a042021-01-26 16:21:45 -0600354 return std::count_if(_sensors.begin(), _sensors.end(),
355 [](const auto& s) { return !s->functional(); });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500356}
357
Matt Spinlerabf8da32017-04-27 14:08:45 -0500358bool Fan::outOfRange(const TachSensor& sensor)
359{
Mike Cappsfdcd5db2021-05-20 12:47:10 -0400360 if (!sensor.hasOwner())
Matt Spinlerabf8da32017-04-27 14:08:45 -0500361 {
362 return true;
363 }
364
Mike Cappsfdcd5db2021-05-20 12:47:10 -0400365 auto actual = static_cast<uint64_t>(sensor.getInput());
366 auto range = sensor.getRange(_deviation);
367
Matthew Barth8a8aa442021-11-19 14:13:13 -0600368 return ((actual < range.first) ||
369 (range.second && actual > range.second.value()));
Matt Spinlerabf8da32017-04-27 14:08:45 -0500370}
371
Jolie Ku69f2f482020-10-21 09:59:43 +0800372void Fan::updateState(TachSensor& sensor)
Matt Spinlera9406a72017-04-27 14:29:24 -0500373{
Matt Spinler7d135642021-02-04 12:44:17 -0600374 if (!_system.isPowerOn())
375 {
376 return;
377 }
378
Matthew Barth8a8aa442021-11-19 14:13:13 -0600379 auto range = sensor.getRange(_deviation);
380 std::string rangeMax = "NoMax";
381 if (range.second)
382 {
383 rangeMax = std::to_string(range.second.value());
384 }
385
Matthew Barthe11cbc62018-02-20 12:11:07 -0600386 sensor.setFunctional(!sensor.functional());
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500387 getLogger().log(
388 fmt::format("Setting tach sensor {} functional state to {}. "
Matthew Barth7c23a042021-01-26 16:21:45 -0600389 "[target = {}, input = {}, allowed range = ({} - {})]",
390 sensor.name(), sensor.functional(), sensor.getTarget(),
Matthew Barth8a8aa442021-11-19 14:13:13 -0600391 sensor.getInput(), range.first, rangeMax));
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500392
393 // A zero value for _numSensorFailsForNonFunc means we aren't dealing
394 // with fan FRU functional status, only sensor functional status.
395 if (_numSensorFailsForNonFunc)
Matthew Barthe11cbc62018-02-20 12:11:07 -0600396 {
Matthew Barth7c23a042021-01-26 16:21:45 -0600397 auto numNonFuncSensors = countNonFunctionalSensors();
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500398 // If the fan was nonfunctional and enough sensors are now OK,
Matthew Barthcceffdd2021-05-20 12:17:21 -0500399 // the fan can be set to functional as long as `set_func_on_present` was
400 // not set
401 if (!_setFuncOnPresent && !_functional &&
402 !(numNonFuncSensors >= _numSensorFailsForNonFunc))
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500403 {
Matthew Barth7c23a042021-01-26 16:21:45 -0600404 getLogger().log(fmt::format("Setting fan {} to functional, number "
405 "of nonfunctional sensors = {}",
406 _name, numNonFuncSensors));
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500407 updateInventory(true);
408 }
Matt Spinlera9406a72017-04-27 14:29:24 -0500409
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500410 // If the fan is currently functional, but too many
411 // contained sensors are now nonfunctional, update
Matthew Barth7c23a042021-01-26 16:21:45 -0600412 // the fan to nonfunctional.
413 if (_functional && (numNonFuncSensors >= _numSensorFailsForNonFunc))
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500414 {
Matthew Barth7c23a042021-01-26 16:21:45 -0600415 getLogger().log(fmt::format("Setting fan {} to nonfunctional, "
416 "number of nonfunctional sensors = {}",
417 _name, numNonFuncSensors));
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500418 updateInventory(false);
419 }
Matt Spinlerb1e18512017-04-27 14:42:33 -0500420 }
Matt Spinlerb63aa092020-10-14 09:45:11 -0500421
422 _system.fanStatusChange(*this);
Matt Spinlera9406a72017-04-27 14:29:24 -0500423}
424
Mike Capps9ff48772021-07-19 14:49:43 -0400425bool Fan::updateInventory(bool functional)
Matt Spinlerb1e18512017-04-27 14:42:33 -0500426{
Mike Capps9ff48772021-07-19 14:49:43 -0400427 bool dbusError = false;
428
429 try
Matt Spinlerb1e18512017-04-27 14:42:33 -0500430 {
Mike Capps9ff48772021-07-19 14:49:43 -0400431 auto objectMap =
432 util::getObjMap<bool>(_name, util::OPERATIONAL_STATUS_INTF,
433 util::FUNCTIONAL_PROPERTY, functional);
434
435 auto response = util::SDBusPlus::lookupAndCallMethod(
436 _bus, util::INVENTORY_PATH, util::INVENTORY_INTF, "Notify",
437 objectMap);
438
439 if (response.is_method_error())
440 {
441 log<level::ERR>("Error in Notify call to update inventory");
442
443 dbusError = true;
444 }
445 }
446 catch (const util::DBusError& e)
447 {
448 dbusError = true;
449
450 getLogger().log(
451 fmt::format("D-Bus Exception reading/updating inventory : {}",
452 e.what()),
453 Logger::error);
Matt Spinlerb1e18512017-04-27 14:42:33 -0500454 }
455
Matthew Barth177fe982020-05-26 11:05:19 -0500456 // This will always track the current state of the inventory.
Matt Spinlerb1e18512017-04-27 14:42:33 -0500457 _functional = functional;
Mike Capps9ff48772021-07-19 14:49:43 -0400458
459 return dbusError;
Matt Spinlerb1e18512017-04-27 14:42:33 -0500460}
461
Matt Spinlerb63aa092020-10-14 09:45:11 -0500462void Fan::presenceChanged(sdbusplus::message::message& msg)
463{
464 std::string interface;
465 std::map<std::string, std::variant<bool>> properties;
466
467 msg.read(interface, properties);
468
469 auto presentProp = properties.find("Present");
470 if (presentProp != properties.end())
471 {
472 _present = std::get<bool>(presentProp->second);
473
Matt Spinler27f6b682020-10-27 08:43:37 -0500474 getLogger().log(
Matt Spinlerac372972021-01-25 15:11:22 -0600475 fmt::format("Fan {} presence state change to {}", _name, _present));
Matt Spinler27f6b682020-10-27 08:43:37 -0500476
Matt Spinlerb63aa092020-10-14 09:45:11 -0500477 _system.fanStatusChange(*this);
Matt Spinler27f6b682020-10-27 08:43:37 -0500478
Matt Spinlera3584bd2021-03-29 15:48:30 -0500479 if (_present && _setFuncOnPresent)
480 {
481 updateInventory(true);
482 std::for_each(_sensors.begin(), _sensors.end(), [](auto& sensor) {
483 sensor->setFunctional(true);
484 sensor->resetMethod();
485 });
486 }
487
Matt Spinler27f6b682020-10-27 08:43:37 -0500488 if (_fanMissingErrorDelay)
489 {
Matt Spinler7d135642021-02-04 12:44:17 -0600490 if (!_present && _system.isPowerOn())
Matt Spinler27f6b682020-10-27 08:43:37 -0500491 {
492 _fanMissingErrorTimer->restartOnce(
493 std::chrono::seconds{*_fanMissingErrorDelay});
494 }
Matt Spinler7d135642021-02-04 12:44:17 -0600495 else if (_present && _fanMissingErrorTimer->isEnabled())
Matt Spinler27f6b682020-10-27 08:43:37 -0500496 {
497 _fanMissingErrorTimer->setEnabled(false);
498 }
499 }
Matt Spinlerb63aa092020-10-14 09:45:11 -0500500 }
501}
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500502
503void Fan::sensorErrorTimerExpired(const TachSensor& sensor)
504{
Matt Spinler7d135642021-02-04 12:44:17 -0600505 if (_present && _system.isPowerOn())
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500506 {
507 _system.sensorErrorTimerExpired(*this, sensor);
508 }
509}
510
Matt Spinler7d135642021-02-04 12:44:17 -0600511void Fan::powerStateChanged(bool powerStateOn)
512{
513#ifdef MONITOR_USE_JSON
514 if (powerStateOn)
515 {
Matt Spinler7d135642021-02-04 12:44:17 -0600516 _monitorTimer.restartOnce(std::chrono::seconds(_monitorDelay));
517
Matt Spinlerbb449c12021-06-14 11:45:28 -0600518 _numSensorsOnDBusAtPowerOn = 0;
519
520 std::for_each(_sensors.begin(), _sensors.end(), [this](auto& sensor) {
521 try
522 {
523 // Force a getProperty call. If sensor is on D-Bus,
524 // then make sure it's functional.
525 sensor->updateTachAndTarget();
526
527 _numSensorsOnDBusAtPowerOn++;
528
529 if (_present)
530 {
531 // If not functional, set it back to functional.
532 if (!sensor->functional())
533 {
534 sensor->setFunctional(true);
535 _system.fanStatusChange(*this, true);
536 }
537
538 // Set the counters back to zero
539 if (sensor->getMethod() == MethodMode::count)
540 {
541 sensor->resetMethod();
542 }
543 }
544 }
545 catch (const util::DBusError& e)
546 {
547 // Properties still aren't on D-Bus. Let startMonitor()
548 // deal with it, or maybe System::powerStateChanged() if
549 // there aren't any sensors at all on D-Bus.
550 getLogger().log(fmt::format(
551 "At power on, tach sensor {} value not on D-Bus",
552 sensor->name()));
553 }
554 });
555
Matt Spinler4283c5d2021-03-01 15:56:00 -0600556 if (_present)
557 {
Matt Spinler4283c5d2021-03-01 15:56:00 -0600558 // If configured to change functional state on the fan itself,
559 // Set it back to true now if necessary.
560 if (_numSensorFailsForNonFunc)
561 {
562 if (!_functional &&
563 (countNonFunctionalSensors() < _numSensorFailsForNonFunc))
564 {
565 updateInventory(true);
566 }
567 }
568 }
569 else
Matt Spinler7d135642021-02-04 12:44:17 -0600570 {
571 getLogger().log(
572 fmt::format("At power on, fan {} is missing", _name));
573
574 if (_fanMissingErrorTimer)
575 {
576 _fanMissingErrorTimer->restartOnce(
577 std::chrono::seconds{*_fanMissingErrorDelay});
578 }
579 }
580 }
581 else
582 {
583 _monitorReady = false;
584
585 if (_monitorTimer.isEnabled())
586 {
587 _monitorTimer.setEnabled(false);
588 }
589
590 if (_fanMissingErrorTimer && _fanMissingErrorTimer->isEnabled())
591 {
592 _fanMissingErrorTimer->setEnabled(false);
593 }
594
595 std::for_each(_sensors.begin(), _sensors.end(), [](auto& sensor) {
596 if (sensor->timerRunning())
597 {
598 sensor->stopTimer();
599 }
Matt Spinler623635c2021-03-29 13:13:59 -0500600
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600601 sensor->stopCountTimer();
602 });
Matt Spinler7d135642021-02-04 12:44:17 -0600603 }
604#endif
605}
606
Matthew Barth177fe982020-05-26 11:05:19 -0500607} // namespace monitor
608} // namespace fan
609} // namespace phosphor