blob: 52b403199c12b3f0c6c3f35e0b4f0ebca1342395 [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)),
65 _countInterval(std::get<countIntervalField>(def))
Matt Spinlerabf8da32017-04-27 14:08:45 -050066{
Matt Spinler623635c2021-03-29 13:13:59 -050067 bool enableCountTimer = false;
68
Matt Spinlerae1f8ef2020-10-14 16:15:51 -050069 // Start from a known state of functional (even if
70 // _numSensorFailsForNonFunc is 0)
Jolie Ku4c3c24f2020-09-09 11:01:46 +080071 updateInventory(true);
72
Matthew Barth0a9fe162018-01-26 12:53:15 -060073 // Setup tach sensors for monitoring
74 auto& sensors = std::get<sensorListField>(def);
75 for (auto& s : sensors)
76 {
Matt Spinler4283c5d2021-03-01 15:56:00 -060077 _sensors.emplace_back(std::make_shared<TachSensor>(
78 mode, bus, *this, std::get<sensorNameField>(s),
79 std::get<hasTargetField>(s), std::get<funcDelay>(def),
80 std::get<targetInterfaceField>(s), std::get<factorField>(s),
81 std::get<offsetField>(s), std::get<methodField>(def),
82 std::get<thresholdField>(s), std::get<timeoutField>(def),
83 std::get<nonfuncRotorErrDelayField>(def), event));
Matthew Barth0a9fe162018-01-26 12:53:15 -060084
Matt Spinler4283c5d2021-03-01 15:56:00 -060085 _trustManager->registerSensor(_sensors.back());
Matt Spinler623635c2021-03-29 13:13:59 -050086 if (_sensors.back()->getMethod() == MethodMode::count)
87 {
88 enableCountTimer = true;
89 }
90 }
91
92 // If the error checking method will be 'count', then it needs a timer.
93 // The timer is repeating but is disabled immediately because it doesn't
94 // need to start yet.
95 if (enableCountTimer)
96 {
97 _countTimer = std::make_unique<
98 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
99 event, std::bind(&Fan::countTimerExpired, this),
100 std::chrono::seconds(_countInterval));
101
102 _countTimer->setEnabled(false);
Matthew Barth0a9fe162018-01-26 12:53:15 -0600103 }
104
Matt Spinlerb0412d02020-10-12 16:53:52 -0500105#ifndef MONITOR_USE_JSON
Matthew Barth0a9fe162018-01-26 12:53:15 -0600106 // Check current tach state when entering monitor mode
Matthew Barth6ad28432017-08-22 11:18:19 -0500107 if (mode != Mode::init)
108 {
Matt Spinlerb0412d02020-10-12 16:53:52 -0500109 _monitorReady = true;
110
Matthew Barth177fe982020-05-26 11:05:19 -0500111 // The TachSensors will now have already read the input
112 // and target values, so check them.
Matthew Barth6ad28432017-08-22 11:18:19 -0500113 tachChanged();
114 }
Matt Spinlerb0412d02020-10-12 16:53:52 -0500115#else
Matt Spinler7d135642021-02-04 12:44:17 -0600116 if (_system.isPowerOn())
117 {
118 _monitorTimer.restartOnce(std::chrono::seconds(_monitorDelay));
119 }
Matt Spinlerb0412d02020-10-12 16:53:52 -0500120#endif
Matt Spinlerb63aa092020-10-14 09:45:11 -0500121
Matt Spinler27f6b682020-10-27 08:43:37 -0500122 if (_fanMissingErrorDelay)
123 {
124 _fanMissingErrorTimer = std::make_unique<
125 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
126 event, std::bind(&System::fanMissingErrorTimerExpired, &system,
127 std::ref(*this)));
Matt Spinler7d135642021-02-04 12:44:17 -0600128 }
Matt Spinler27f6b682020-10-27 08:43:37 -0500129
Matt Spinler7d135642021-02-04 12:44:17 -0600130 try
131 {
132 _present = util::SDBusPlus::getProperty<bool>(
133 util::INVENTORY_PATH + _name, util::INV_ITEM_IFACE, "Present");
134
135 if (!_present)
Matt Spinler27f6b682020-10-27 08:43:37 -0500136 {
Matt Spinlerac372972021-01-25 15:11:22 -0600137 getLogger().log(
138 fmt::format("On startup, fan {} is missing", _name));
Matt Spinler7d135642021-02-04 12:44:17 -0600139 if (_system.isPowerOn() && _fanMissingErrorTimer)
140 {
141 _fanMissingErrorTimer->restartOnce(
142 std::chrono::seconds{*_fanMissingErrorDelay});
143 }
144 }
145 }
146 catch (const util::DBusServiceError& e)
147 {
148 // This could happen on the first BMC boot if the presence
149 // detect app hasn't started yet and there isn't an inventory
150 // cache yet.
151 }
152}
153
154void Fan::presenceIfaceAdded(sdbusplus::message::message& msg)
155{
156 sdbusplus::message::object_path path;
157 std::map<std::string, std::map<std::string, std::variant<bool>>> interfaces;
158
159 msg.read(path, interfaces);
160
161 auto properties = interfaces.find(util::INV_ITEM_IFACE);
162 if (properties == interfaces.end())
163 {
164 return;
165 }
166
167 auto property = properties->second.find("Present");
168 if (property == properties->second.end())
169 {
170 return;
171 }
172
173 _present = std::get<bool>(property->second);
174
175 if (!_present)
176 {
177 getLogger().log(fmt::format(
178 "New fan {} interface added and fan is not present", _name));
179 if (_system.isPowerOn() && _fanMissingErrorTimer)
180 {
Matt Spinler27f6b682020-10-27 08:43:37 -0500181 _fanMissingErrorTimer->restartOnce(
182 std::chrono::seconds{*_fanMissingErrorDelay});
183 }
184 }
Matt Spinler7d135642021-02-04 12:44:17 -0600185
186 _system.fanStatusChange(*this);
Matt Spinlerb0412d02020-10-12 16:53:52 -0500187}
188
189void Fan::startMonitor()
190{
191 _monitorReady = true;
192
Matt Spinler623635c2021-03-29 13:13:59 -0500193 if (_countTimer)
194 {
195 _countTimer->resetRemaining();
196 _countTimer->setEnabled(true);
197 }
198
Matt Spinler4283c5d2021-03-01 15:56:00 -0600199 std::for_each(_sensors.begin(), _sensors.end(), [this](auto& sensor) {
200 if (_present)
201 {
202 try
203 {
204 // Force a getProperty call to check if the tach sensor is
205 // on D-Bus. If it isn't, now set it to nonfunctional.
206 // This isn't done earlier so that code watching for
207 // nonfunctional tach sensors doesn't take actions before
208 // those sensors show up on D-Bus.
209 sensor->updateTachAndTarget();
210 tachChanged(*sensor);
211 }
212 catch (const util::DBusServiceError& e)
213 {
214 // The tach property still isn't on D-Bus, ensure
215 // sensor is nonfunctional.
216 getLogger().log(fmt::format(
217 "Monitoring starting but {} sensor value not on D-Bus",
218 sensor->name()));
219
220 sensor->setFunctional(false);
221
222 if (_numSensorFailsForNonFunc)
223 {
224 if (_functional && (countNonFunctionalSensors() >=
225 _numSensorFailsForNonFunc))
226 {
227 updateInventory(false);
228 }
229 }
230
231 _system.fanStatusChange(*this);
232 }
233 }
234 });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500235}
236
Matt Spinlerebaae612017-04-27 14:21:48 -0500237void Fan::tachChanged()
238{
Matt Spinlerb0412d02020-10-12 16:53:52 -0500239 if (_monitorReady)
Matt Spinlerebaae612017-04-27 14:21:48 -0500240 {
Matt Spinlerb0412d02020-10-12 16:53:52 -0500241 for (auto& s : _sensors)
242 {
243 tachChanged(*s);
244 }
Matt Spinlerebaae612017-04-27 14:21:48 -0500245 }
246}
247
Matt Spinlerebaae612017-04-27 14:21:48 -0500248void Fan::tachChanged(TachSensor& sensor)
249{
Matt Spinler7d135642021-02-04 12:44:17 -0600250 if (!_system.isPowerOn() || !_monitorReady)
251 {
252 return;
253 }
254
Matt Spinlerc39e8592017-09-28 13:13:08 -0500255 if (_trustManager->active())
256 {
257 if (!_trustManager->checkTrust(sensor))
258 {
259 return;
260 }
261 }
262
Matt Spinler623635c2021-03-29 13:13:59 -0500263 // If using the timebased method to determine functional status,
264 // check now, otherwise let _countTimer handle it. A timer is
265 // used for the count method so that stuck sensors will continue
266 // to be checked.
267 if (sensor.getMethod() == MethodMode::timebased)
268 {
269 process(sensor);
270 }
271}
272
273void Fan::countTimerExpired()
274{
275 // For sensors that use the 'count' method, time to check their
276 // status and increment/decrement counts as necessary.
277 for (auto& sensor : _sensors)
278 {
279 if (_trustManager->active() && !_trustManager->checkTrust(*sensor))
280 {
281 continue;
282 }
283 process(*sensor);
284 }
Matthew Barthfcb0dbc2021-02-10 14:23:39 -0600285}
286
287void Fan::process(TachSensor& sensor)
288{
Matthew Barth177fe982020-05-26 11:05:19 -0500289 // If this sensor is out of range at this moment, start
290 // its timer, at the end of which the inventory
291 // for the fan may get updated to not functional.
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500292
Matthew Barth177fe982020-05-26 11:05:19 -0500293 // If this sensor is OK, put everything back into a good state.
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500294
295 if (outOfRange(sensor))
296 {
Matthew Barthe11cbc62018-02-20 12:11:07 -0600297 if (sensor.functional())
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500298 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800299 switch (sensor.getMethod())
300 {
301 case MethodMode::timebased:
302 // Start nonfunctional timer if not already running
303 sensor.startTimer(TimerMode::nonfunc);
304 break;
305 case MethodMode::count:
306 sensor.setCounter(true);
307 if (sensor.getCounter() >= sensor.getThreshold())
308 {
309 updateState(sensor);
310 }
311 break;
312 }
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500313 }
314 }
315 else
316 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800317 switch (sensor.getMethod())
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500318 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800319 case MethodMode::timebased:
320 if (sensor.functional())
321 {
Matthew Barth11b5d8f2021-01-28 14:04:09 -0600322 if (sensor.timerRunning())
323 {
324 sensor.stopTimer();
325 }
Jolie Ku69f2f482020-10-21 09:59:43 +0800326 }
327 else
328 {
329 // Start functional timer if not already running
330 sensor.startTimer(TimerMode::func);
331 }
332 break;
333 case MethodMode::count:
334 sensor.setCounter(false);
335 if (!sensor.functional() && sensor.getCounter() == 0)
336 {
337 updateState(sensor);
338 }
339 break;
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500340 }
341 }
Matt Spinlerebaae612017-04-27 14:21:48 -0500342}
343
Matthew Barthf552ea52018-01-15 16:22:04 -0600344uint64_t Fan::findTargetSpeed()
Matt Spinlerabf8da32017-04-27 14:08:45 -0500345{
346 uint64_t target = 0;
Matthew Barth177fe982020-05-26 11:05:19 -0500347 // The sensor doesn't support a target,
348 // so get it from another sensor.
Matthew Barthf552ea52018-01-15 16:22:04 -0600349 auto s = std::find_if(_sensors.begin(), _sensors.end(),
Matthew Barth177fe982020-05-26 11:05:19 -0500350 [](const auto& s) { return s->hasTarget(); });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500351
Matthew Barthf552ea52018-01-15 16:22:04 -0600352 if (s != _sensors.end())
Matt Spinlerabf8da32017-04-27 14:08:45 -0500353 {
Matthew Barthf552ea52018-01-15 16:22:04 -0600354 target = (*s)->getTarget();
Matt Spinlerabf8da32017-04-27 14:08:45 -0500355 }
356
357 return target;
358}
359
Matthew Barth7c23a042021-01-26 16:21:45 -0600360size_t Fan::countNonFunctionalSensors()
Matt Spinlerabf8da32017-04-27 14:08:45 -0500361{
Matthew Barth7c23a042021-01-26 16:21:45 -0600362 return std::count_if(_sensors.begin(), _sensors.end(),
363 [](const auto& s) { return !s->functional(); });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500364}
365
Matt Spinlerabf8da32017-04-27 14:08:45 -0500366bool Fan::outOfRange(const TachSensor& sensor)
367{
368 auto actual = static_cast<uint64_t>(sensor.getInput());
Matthew Barth7c23a042021-01-26 16:21:45 -0600369 auto range = sensor.getRange(_deviation);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500370
Matthew Barth7c23a042021-01-26 16:21:45 -0600371 if ((actual < range.first) || (actual > range.second))
Matt Spinlerabf8da32017-04-27 14:08:45 -0500372 {
373 return true;
374 }
375
376 return false;
377}
378
Jolie Ku69f2f482020-10-21 09:59:43 +0800379void Fan::updateState(TachSensor& sensor)
Matt Spinlera9406a72017-04-27 14:29:24 -0500380{
Matthew Barth7c23a042021-01-26 16:21:45 -0600381 auto range = sensor.getRange(_deviation);
Matt Spinler7d135642021-02-04 12:44:17 -0600382
383 if (!_system.isPowerOn())
384 {
385 return;
386 }
387
Matthew Barthe11cbc62018-02-20 12:11:07 -0600388 sensor.setFunctional(!sensor.functional());
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500389 getLogger().log(
390 fmt::format("Setting tach sensor {} functional state to {}. "
Matthew Barth7c23a042021-01-26 16:21:45 -0600391 "[target = {}, input = {}, allowed range = ({} - {})]",
392 sensor.name(), sensor.functional(), sensor.getTarget(),
393 sensor.getInput(), range.first, range.second));
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500394
395 // A zero value for _numSensorFailsForNonFunc means we aren't dealing
396 // with fan FRU functional status, only sensor functional status.
397 if (_numSensorFailsForNonFunc)
Matthew Barthe11cbc62018-02-20 12:11:07 -0600398 {
Matthew Barth7c23a042021-01-26 16:21:45 -0600399 auto numNonFuncSensors = countNonFunctionalSensors();
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500400 // If the fan was nonfunctional and enough sensors are now OK,
Matthew Barth7c23a042021-01-26 16:21:45 -0600401 // the fan can be set to functional
402 if (!_functional && !(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
Matt Spinlerb1e18512017-04-27 14:42:33 -0500425void Fan::updateInventory(bool functional)
426{
Matthew Barth177fe982020-05-26 11:05:19 -0500427 auto objectMap =
428 util::getObjMap<bool>(_name, util::OPERATIONAL_STATUS_INTF,
429 util::FUNCTIONAL_PROPERTY, functional);
Matthew Barth51dd1852017-11-16 15:21:13 -0600430 auto response = util::SDBusPlus::lookupAndCallMethod(
Matthew Barth177fe982020-05-26 11:05:19 -0500431 _bus, util::INVENTORY_PATH, util::INVENTORY_INTF, "Notify", objectMap);
Matt Spinlerb1e18512017-04-27 14:42:33 -0500432 if (response.is_method_error())
433 {
434 log<level::ERR>("Error in Notify call to update inventory");
435 return;
436 }
437
Matthew Barth177fe982020-05-26 11:05:19 -0500438 // This will always track the current state of the inventory.
Matt Spinlerb1e18512017-04-27 14:42:33 -0500439 _functional = functional;
440}
441
Matt Spinlerb63aa092020-10-14 09:45:11 -0500442void Fan::presenceChanged(sdbusplus::message::message& msg)
443{
444 std::string interface;
445 std::map<std::string, std::variant<bool>> properties;
446
447 msg.read(interface, properties);
448
449 auto presentProp = properties.find("Present");
450 if (presentProp != properties.end())
451 {
452 _present = std::get<bool>(presentProp->second);
453
Matt Spinler27f6b682020-10-27 08:43:37 -0500454 getLogger().log(
Matt Spinlerac372972021-01-25 15:11:22 -0600455 fmt::format("Fan {} presence state change to {}", _name, _present));
Matt Spinler27f6b682020-10-27 08:43:37 -0500456
Matt Spinlerb63aa092020-10-14 09:45:11 -0500457 _system.fanStatusChange(*this);
Matt Spinler27f6b682020-10-27 08:43:37 -0500458
459 if (_fanMissingErrorDelay)
460 {
Matt Spinler7d135642021-02-04 12:44:17 -0600461 if (!_present && _system.isPowerOn())
Matt Spinler27f6b682020-10-27 08:43:37 -0500462 {
463 _fanMissingErrorTimer->restartOnce(
464 std::chrono::seconds{*_fanMissingErrorDelay});
465 }
Matt Spinler7d135642021-02-04 12:44:17 -0600466 else if (_present && _fanMissingErrorTimer->isEnabled())
Matt Spinler27f6b682020-10-27 08:43:37 -0500467 {
468 _fanMissingErrorTimer->setEnabled(false);
469 }
470 }
Matt Spinlerb63aa092020-10-14 09:45:11 -0500471 }
472}
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500473
474void Fan::sensorErrorTimerExpired(const TachSensor& sensor)
475{
Matt Spinler7d135642021-02-04 12:44:17 -0600476 if (_present && _system.isPowerOn())
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500477 {
478 _system.sensorErrorTimerExpired(*this, sensor);
479 }
480}
481
Matt Spinler7d135642021-02-04 12:44:17 -0600482void Fan::powerStateChanged(bool powerStateOn)
483{
484#ifdef MONITOR_USE_JSON
485 if (powerStateOn)
486 {
Matt Spinler7d135642021-02-04 12:44:17 -0600487 _monitorTimer.restartOnce(std::chrono::seconds(_monitorDelay));
488
Matt Spinler4283c5d2021-03-01 15:56:00 -0600489 if (_present)
490 {
491 std::for_each(
492 _sensors.begin(), _sensors.end(), [this](auto& sensor) {
493 try
494 {
495 // Force a getProperty call. If sensor is on D-Bus,
496 // then make sure it's functional.
497 sensor->updateTachAndTarget();
498
499 // If not functional, set it back to functional.
500 if (!sensor->functional())
501 {
502 sensor->setFunctional(true);
503 _system.fanStatusChange(*this, true);
504 }
Matt Spinler623635c2021-03-29 13:13:59 -0500505
506 // Set the counters back to zero
507 if (sensor->getMethod() == MethodMode::count)
508 {
509 sensor->resetMethod();
510 }
Matt Spinler4283c5d2021-03-01 15:56:00 -0600511 }
512 catch (const util::DBusServiceError& e)
513 {
514 // Properties still aren't on D-Bus. Let startMonitor()
515 // deal with it.
516 getLogger().log(fmt::format(
517 "At power on, tach sensor {} value not on D-Bus",
518 sensor->name()));
519 }
520 });
521
522 // If configured to change functional state on the fan itself,
523 // Set it back to true now if necessary.
524 if (_numSensorFailsForNonFunc)
525 {
526 if (!_functional &&
527 (countNonFunctionalSensors() < _numSensorFailsForNonFunc))
528 {
529 updateInventory(true);
530 }
531 }
532 }
533 else
Matt Spinler7d135642021-02-04 12:44:17 -0600534 {
535 getLogger().log(
536 fmt::format("At power on, fan {} is missing", _name));
537
538 if (_fanMissingErrorTimer)
539 {
540 _fanMissingErrorTimer->restartOnce(
541 std::chrono::seconds{*_fanMissingErrorDelay});
542 }
543 }
544 }
545 else
546 {
547 _monitorReady = false;
548
549 if (_monitorTimer.isEnabled())
550 {
551 _monitorTimer.setEnabled(false);
552 }
553
554 if (_fanMissingErrorTimer && _fanMissingErrorTimer->isEnabled())
555 {
556 _fanMissingErrorTimer->setEnabled(false);
557 }
558
559 std::for_each(_sensors.begin(), _sensors.end(), [](auto& sensor) {
560 if (sensor->timerRunning())
561 {
562 sensor->stopTimer();
563 }
564 });
Matt Spinler623635c2021-03-29 13:13:59 -0500565
566 if (_countTimer)
567 {
568 _countTimer->setEnabled(false);
569 }
Matt Spinler7d135642021-02-04 12:44:17 -0600570 }
571#endif
572}
573
Matthew Barth177fe982020-05-26 11:05:19 -0500574} // namespace monitor
575} // namespace fan
576} // namespace phosphor