blob: a8efc4ccd04c31d8398f798cc5f37e476fb6dfca [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 _countInterval(std::get<countIntervalField>(def)),
66 _setFuncOnPresent(std::get<funcOnPresentField>(def))
Matt Spinlerabf8da32017-04-27 14:08:45 -050067{
Matt Spinler623635c2021-03-29 13:13:59 -050068 bool enableCountTimer = false;
69
Matt Spinlerae1f8ef2020-10-14 16:15:51 -050070 // Start from a known state of functional (even if
71 // _numSensorFailsForNonFunc is 0)
Jolie Ku4c3c24f2020-09-09 11:01:46 +080072 updateInventory(true);
73
Matthew Barth0a9fe162018-01-26 12:53:15 -060074 // Setup tach sensors for monitoring
75 auto& sensors = std::get<sensorListField>(def);
76 for (auto& s : sensors)
77 {
Matt Spinler4283c5d2021-03-01 15:56:00 -060078 _sensors.emplace_back(std::make_shared<TachSensor>(
79 mode, bus, *this, std::get<sensorNameField>(s),
80 std::get<hasTargetField>(s), std::get<funcDelay>(def),
81 std::get<targetInterfaceField>(s), std::get<factorField>(s),
82 std::get<offsetField>(s), std::get<methodField>(def),
83 std::get<thresholdField>(s), std::get<timeoutField>(def),
84 std::get<nonfuncRotorErrDelayField>(def), event));
Matthew Barth0a9fe162018-01-26 12:53:15 -060085
Matt Spinler4283c5d2021-03-01 15:56:00 -060086 _trustManager->registerSensor(_sensors.back());
Matt Spinler623635c2021-03-29 13:13:59 -050087 if (_sensors.back()->getMethod() == MethodMode::count)
88 {
89 enableCountTimer = true;
90 }
91 }
92
93 // If the error checking method will be 'count', then it needs a timer.
94 // The timer is repeating but is disabled immediately because it doesn't
95 // need to start yet.
96 if (enableCountTimer)
97 {
98 _countTimer = std::make_unique<
99 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
100 event, std::bind(&Fan::countTimerExpired, this),
101 std::chrono::seconds(_countInterval));
102
103 _countTimer->setEnabled(false);
Matthew Barth0a9fe162018-01-26 12:53:15 -0600104 }
105
Matt Spinlerb0412d02020-10-12 16:53:52 -0500106#ifndef MONITOR_USE_JSON
Matthew Barth0a9fe162018-01-26 12:53:15 -0600107 // Check current tach state when entering monitor mode
Matthew Barth6ad28432017-08-22 11:18:19 -0500108 if (mode != Mode::init)
109 {
Matt Spinlerb0412d02020-10-12 16:53:52 -0500110 _monitorReady = true;
111
Matthew Barth177fe982020-05-26 11:05:19 -0500112 // The TachSensors will now have already read the input
113 // and target values, so check them.
Matthew Barth6ad28432017-08-22 11:18:19 -0500114 tachChanged();
115 }
Matt Spinlerb0412d02020-10-12 16:53:52 -0500116#else
Matt Spinler7d135642021-02-04 12:44:17 -0600117 if (_system.isPowerOn())
118 {
119 _monitorTimer.restartOnce(std::chrono::seconds(_monitorDelay));
120 }
Matt Spinlerb0412d02020-10-12 16:53:52 -0500121#endif
Matt Spinlerb63aa092020-10-14 09:45:11 -0500122
Matt Spinler27f6b682020-10-27 08:43:37 -0500123 if (_fanMissingErrorDelay)
124 {
125 _fanMissingErrorTimer = std::make_unique<
126 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
127 event, std::bind(&System::fanMissingErrorTimerExpired, &system,
128 std::ref(*this)));
Matt Spinler7d135642021-02-04 12:44:17 -0600129 }
Matt Spinler27f6b682020-10-27 08:43:37 -0500130
Matt Spinler7d135642021-02-04 12:44:17 -0600131 try
132 {
133 _present = util::SDBusPlus::getProperty<bool>(
134 util::INVENTORY_PATH + _name, util::INV_ITEM_IFACE, "Present");
135
136 if (!_present)
Matt Spinler27f6b682020-10-27 08:43:37 -0500137 {
Matt Spinlerac372972021-01-25 15:11:22 -0600138 getLogger().log(
139 fmt::format("On startup, fan {} is missing", _name));
Matt Spinler7d135642021-02-04 12:44:17 -0600140 if (_system.isPowerOn() && _fanMissingErrorTimer)
141 {
142 _fanMissingErrorTimer->restartOnce(
143 std::chrono::seconds{*_fanMissingErrorDelay});
144 }
145 }
146 }
147 catch (const util::DBusServiceError& e)
148 {
149 // This could happen on the first BMC boot if the presence
150 // detect app hasn't started yet and there isn't an inventory
151 // cache yet.
152 }
153}
154
155void Fan::presenceIfaceAdded(sdbusplus::message::message& msg)
156{
157 sdbusplus::message::object_path path;
158 std::map<std::string, std::map<std::string, std::variant<bool>>> interfaces;
159
160 msg.read(path, interfaces);
161
162 auto properties = interfaces.find(util::INV_ITEM_IFACE);
163 if (properties == interfaces.end())
164 {
165 return;
166 }
167
168 auto property = properties->second.find("Present");
169 if (property == properties->second.end())
170 {
171 return;
172 }
173
174 _present = std::get<bool>(property->second);
175
176 if (!_present)
177 {
178 getLogger().log(fmt::format(
179 "New fan {} interface added and fan is not present", _name));
180 if (_system.isPowerOn() && _fanMissingErrorTimer)
181 {
Matt Spinler27f6b682020-10-27 08:43:37 -0500182 _fanMissingErrorTimer->restartOnce(
183 std::chrono::seconds{*_fanMissingErrorDelay});
184 }
185 }
Matt Spinler7d135642021-02-04 12:44:17 -0600186
187 _system.fanStatusChange(*this);
Matt Spinlerb0412d02020-10-12 16:53:52 -0500188}
189
190void Fan::startMonitor()
191{
192 _monitorReady = true;
193
Matt Spinler623635c2021-03-29 13:13:59 -0500194 if (_countTimer)
195 {
196 _countTimer->resetRemaining();
197 _countTimer->setEnabled(true);
198 }
199
Matt Spinler4283c5d2021-03-01 15:56:00 -0600200 std::for_each(_sensors.begin(), _sensors.end(), [this](auto& sensor) {
201 if (_present)
202 {
203 try
204 {
205 // Force a getProperty call to check if the tach sensor is
206 // on D-Bus. If it isn't, now set it to nonfunctional.
207 // This isn't done earlier so that code watching for
208 // nonfunctional tach sensors doesn't take actions before
209 // those sensors show up on D-Bus.
210 sensor->updateTachAndTarget();
211 tachChanged(*sensor);
212 }
213 catch (const util::DBusServiceError& e)
214 {
215 // The tach property still isn't on D-Bus, ensure
216 // sensor is nonfunctional.
217 getLogger().log(fmt::format(
218 "Monitoring starting but {} sensor value not on D-Bus",
219 sensor->name()));
220
221 sensor->setFunctional(false);
222
223 if (_numSensorFailsForNonFunc)
224 {
225 if (_functional && (countNonFunctionalSensors() >=
226 _numSensorFailsForNonFunc))
227 {
228 updateInventory(false);
229 }
230 }
231
232 _system.fanStatusChange(*this);
233 }
234 }
235 });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500236}
237
Matt Spinlerebaae612017-04-27 14:21:48 -0500238void Fan::tachChanged()
239{
Matt Spinlerb0412d02020-10-12 16:53:52 -0500240 if (_monitorReady)
Matt Spinlerebaae612017-04-27 14:21:48 -0500241 {
Matt Spinlerb0412d02020-10-12 16:53:52 -0500242 for (auto& s : _sensors)
243 {
244 tachChanged(*s);
245 }
Matt Spinlerebaae612017-04-27 14:21:48 -0500246 }
247}
248
Matt Spinlerebaae612017-04-27 14:21:48 -0500249void Fan::tachChanged(TachSensor& sensor)
250{
Matt Spinler7d135642021-02-04 12:44:17 -0600251 if (!_system.isPowerOn() || !_monitorReady)
252 {
253 return;
254 }
255
Matt Spinlerc39e8592017-09-28 13:13:08 -0500256 if (_trustManager->active())
257 {
258 if (!_trustManager->checkTrust(sensor))
259 {
260 return;
261 }
262 }
263
Matt Spinler623635c2021-03-29 13:13:59 -0500264 // If using the timebased method to determine functional status,
265 // check now, otherwise let _countTimer handle it. A timer is
266 // used for the count method so that stuck sensors will continue
267 // to be checked.
268 if (sensor.getMethod() == MethodMode::timebased)
269 {
270 process(sensor);
271 }
272}
273
274void Fan::countTimerExpired()
275{
276 // For sensors that use the 'count' method, time to check their
277 // status and increment/decrement counts as necessary.
278 for (auto& sensor : _sensors)
279 {
280 if (_trustManager->active() && !_trustManager->checkTrust(*sensor))
281 {
282 continue;
283 }
284 process(*sensor);
285 }
Matthew Barthfcb0dbc2021-02-10 14:23:39 -0600286}
287
288void Fan::process(TachSensor& sensor)
289{
Matthew Barth177fe982020-05-26 11:05:19 -0500290 // If this sensor is out of range at this moment, start
291 // its timer, at the end of which the inventory
292 // for the fan may get updated to not functional.
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500293
Matthew Barth177fe982020-05-26 11:05:19 -0500294 // If this sensor is OK, put everything back into a good state.
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500295
296 if (outOfRange(sensor))
297 {
Matthew Barthe11cbc62018-02-20 12:11:07 -0600298 if (sensor.functional())
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500299 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800300 switch (sensor.getMethod())
301 {
302 case MethodMode::timebased:
303 // Start nonfunctional timer if not already running
304 sensor.startTimer(TimerMode::nonfunc);
305 break;
306 case MethodMode::count:
307 sensor.setCounter(true);
308 if (sensor.getCounter() >= sensor.getThreshold())
309 {
310 updateState(sensor);
311 }
312 break;
313 }
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500314 }
315 }
316 else
317 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800318 switch (sensor.getMethod())
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500319 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800320 case MethodMode::timebased:
321 if (sensor.functional())
322 {
Matthew Barth11b5d8f2021-01-28 14:04:09 -0600323 if (sensor.timerRunning())
324 {
325 sensor.stopTimer();
326 }
Jolie Ku69f2f482020-10-21 09:59:43 +0800327 }
328 else
329 {
330 // Start functional timer if not already running
331 sensor.startTimer(TimerMode::func);
332 }
333 break;
334 case MethodMode::count:
335 sensor.setCounter(false);
336 if (!sensor.functional() && sensor.getCounter() == 0)
337 {
338 updateState(sensor);
339 }
340 break;
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500341 }
342 }
Matt Spinlerebaae612017-04-27 14:21:48 -0500343}
344
Matthew Barthf552ea52018-01-15 16:22:04 -0600345uint64_t Fan::findTargetSpeed()
Matt Spinlerabf8da32017-04-27 14:08:45 -0500346{
347 uint64_t target = 0;
Matthew Barth177fe982020-05-26 11:05:19 -0500348 // The sensor doesn't support a target,
349 // so get it from another sensor.
Matthew Barthf552ea52018-01-15 16:22:04 -0600350 auto s = std::find_if(_sensors.begin(), _sensors.end(),
Matthew Barth177fe982020-05-26 11:05:19 -0500351 [](const auto& s) { return s->hasTarget(); });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500352
Matthew Barthf552ea52018-01-15 16:22:04 -0600353 if (s != _sensors.end())
Matt Spinlerabf8da32017-04-27 14:08:45 -0500354 {
Matthew Barthf552ea52018-01-15 16:22:04 -0600355 target = (*s)->getTarget();
Matt Spinlerabf8da32017-04-27 14:08:45 -0500356 }
357
358 return target;
359}
360
Matthew Barth7c23a042021-01-26 16:21:45 -0600361size_t Fan::countNonFunctionalSensors()
Matt Spinlerabf8da32017-04-27 14:08:45 -0500362{
Matthew Barth7c23a042021-01-26 16:21:45 -0600363 return std::count_if(_sensors.begin(), _sensors.end(),
364 [](const auto& s) { return !s->functional(); });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500365}
366
Matt Spinlerabf8da32017-04-27 14:08:45 -0500367bool Fan::outOfRange(const TachSensor& sensor)
368{
369 auto actual = static_cast<uint64_t>(sensor.getInput());
Matthew Barth7c23a042021-01-26 16:21:45 -0600370 auto range = sensor.getRange(_deviation);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500371
Matthew Barth7c23a042021-01-26 16:21:45 -0600372 if ((actual < range.first) || (actual > range.second))
Matt Spinlerabf8da32017-04-27 14:08:45 -0500373 {
374 return true;
375 }
376
377 return false;
378}
379
Jolie Ku69f2f482020-10-21 09:59:43 +0800380void Fan::updateState(TachSensor& sensor)
Matt Spinlera9406a72017-04-27 14:29:24 -0500381{
Matthew Barth7c23a042021-01-26 16:21:45 -0600382 auto range = sensor.getRange(_deviation);
Matt Spinler7d135642021-02-04 12:44:17 -0600383
384 if (!_system.isPowerOn())
385 {
386 return;
387 }
388
Matthew Barthe11cbc62018-02-20 12:11:07 -0600389 sensor.setFunctional(!sensor.functional());
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500390 getLogger().log(
391 fmt::format("Setting tach sensor {} functional state to {}. "
Matthew Barth7c23a042021-01-26 16:21:45 -0600392 "[target = {}, input = {}, allowed range = ({} - {})]",
393 sensor.name(), sensor.functional(), sensor.getTarget(),
394 sensor.getInput(), range.first, range.second));
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500395
396 // A zero value for _numSensorFailsForNonFunc means we aren't dealing
397 // with fan FRU functional status, only sensor functional status.
398 if (_numSensorFailsForNonFunc)
Matthew Barthe11cbc62018-02-20 12:11:07 -0600399 {
Matthew Barth7c23a042021-01-26 16:21:45 -0600400 auto numNonFuncSensors = countNonFunctionalSensors();
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500401 // If the fan was nonfunctional and enough sensors are now OK,
Matthew Barthcceffdd2021-05-20 12:17:21 -0500402 // the fan can be set to functional as long as `set_func_on_present` was
403 // not set
404 if (!_setFuncOnPresent && !_functional &&
405 !(numNonFuncSensors >= _numSensorFailsForNonFunc))
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500406 {
Matthew Barth7c23a042021-01-26 16:21:45 -0600407 getLogger().log(fmt::format("Setting fan {} to functional, number "
408 "of nonfunctional sensors = {}",
409 _name, numNonFuncSensors));
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500410 updateInventory(true);
411 }
Matt Spinlera9406a72017-04-27 14:29:24 -0500412
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500413 // If the fan is currently functional, but too many
414 // contained sensors are now nonfunctional, update
Matthew Barth7c23a042021-01-26 16:21:45 -0600415 // the fan to nonfunctional.
416 if (_functional && (numNonFuncSensors >= _numSensorFailsForNonFunc))
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500417 {
Matthew Barth7c23a042021-01-26 16:21:45 -0600418 getLogger().log(fmt::format("Setting fan {} to nonfunctional, "
419 "number of nonfunctional sensors = {}",
420 _name, numNonFuncSensors));
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500421 updateInventory(false);
422 }
Matt Spinlerb1e18512017-04-27 14:42:33 -0500423 }
Matt Spinlerb63aa092020-10-14 09:45:11 -0500424
425 _system.fanStatusChange(*this);
Matt Spinlera9406a72017-04-27 14:29:24 -0500426}
427
Matt Spinlerb1e18512017-04-27 14:42:33 -0500428void Fan::updateInventory(bool functional)
429{
Matthew Barth177fe982020-05-26 11:05:19 -0500430 auto objectMap =
431 util::getObjMap<bool>(_name, util::OPERATIONAL_STATUS_INTF,
432 util::FUNCTIONAL_PROPERTY, functional);
Matthew Barth51dd1852017-11-16 15:21:13 -0600433 auto response = util::SDBusPlus::lookupAndCallMethod(
Matthew Barth177fe982020-05-26 11:05:19 -0500434 _bus, util::INVENTORY_PATH, util::INVENTORY_INTF, "Notify", objectMap);
Matt Spinlerb1e18512017-04-27 14:42:33 -0500435 if (response.is_method_error())
436 {
437 log<level::ERR>("Error in Notify call to update inventory");
438 return;
439 }
440
Matthew Barth177fe982020-05-26 11:05:19 -0500441 // This will always track the current state of the inventory.
Matt Spinlerb1e18512017-04-27 14:42:33 -0500442 _functional = functional;
443}
444
Matt Spinlerb63aa092020-10-14 09:45:11 -0500445void Fan::presenceChanged(sdbusplus::message::message& msg)
446{
447 std::string interface;
448 std::map<std::string, std::variant<bool>> properties;
449
450 msg.read(interface, properties);
451
452 auto presentProp = properties.find("Present");
453 if (presentProp != properties.end())
454 {
455 _present = std::get<bool>(presentProp->second);
456
Matt Spinler27f6b682020-10-27 08:43:37 -0500457 getLogger().log(
Matt Spinlerac372972021-01-25 15:11:22 -0600458 fmt::format("Fan {} presence state change to {}", _name, _present));
Matt Spinler27f6b682020-10-27 08:43:37 -0500459
Matt Spinlerb63aa092020-10-14 09:45:11 -0500460 _system.fanStatusChange(*this);
Matt Spinler27f6b682020-10-27 08:43:37 -0500461
Matt Spinlera3584bd2021-03-29 15:48:30 -0500462 if (_present && _setFuncOnPresent)
463 {
464 updateInventory(true);
465 std::for_each(_sensors.begin(), _sensors.end(), [](auto& sensor) {
466 sensor->setFunctional(true);
467 sensor->resetMethod();
468 });
469 }
470
Matt Spinler27f6b682020-10-27 08:43:37 -0500471 if (_fanMissingErrorDelay)
472 {
Matt Spinler7d135642021-02-04 12:44:17 -0600473 if (!_present && _system.isPowerOn())
Matt Spinler27f6b682020-10-27 08:43:37 -0500474 {
475 _fanMissingErrorTimer->restartOnce(
476 std::chrono::seconds{*_fanMissingErrorDelay});
477 }
Matt Spinler7d135642021-02-04 12:44:17 -0600478 else if (_present && _fanMissingErrorTimer->isEnabled())
Matt Spinler27f6b682020-10-27 08:43:37 -0500479 {
480 _fanMissingErrorTimer->setEnabled(false);
481 }
482 }
Matt Spinlerb63aa092020-10-14 09:45:11 -0500483 }
484}
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500485
486void Fan::sensorErrorTimerExpired(const TachSensor& sensor)
487{
Matt Spinler7d135642021-02-04 12:44:17 -0600488 if (_present && _system.isPowerOn())
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500489 {
490 _system.sensorErrorTimerExpired(*this, sensor);
491 }
492}
493
Matt Spinler7d135642021-02-04 12:44:17 -0600494void Fan::powerStateChanged(bool powerStateOn)
495{
496#ifdef MONITOR_USE_JSON
497 if (powerStateOn)
498 {
Matt Spinler7d135642021-02-04 12:44:17 -0600499 _monitorTimer.restartOnce(std::chrono::seconds(_monitorDelay));
500
Matt Spinler4283c5d2021-03-01 15:56:00 -0600501 if (_present)
502 {
503 std::for_each(
504 _sensors.begin(), _sensors.end(), [this](auto& sensor) {
505 try
506 {
507 // Force a getProperty call. If sensor is on D-Bus,
508 // then make sure it's functional.
509 sensor->updateTachAndTarget();
510
511 // If not functional, set it back to functional.
512 if (!sensor->functional())
513 {
514 sensor->setFunctional(true);
515 _system.fanStatusChange(*this, true);
516 }
Matt Spinler623635c2021-03-29 13:13:59 -0500517
518 // Set the counters back to zero
519 if (sensor->getMethod() == MethodMode::count)
520 {
521 sensor->resetMethod();
522 }
Matt Spinler4283c5d2021-03-01 15:56:00 -0600523 }
524 catch (const util::DBusServiceError& e)
525 {
526 // Properties still aren't on D-Bus. Let startMonitor()
527 // deal with it.
528 getLogger().log(fmt::format(
529 "At power on, tach sensor {} value not on D-Bus",
530 sensor->name()));
531 }
532 });
533
534 // If configured to change functional state on the fan itself,
535 // Set it back to true now if necessary.
536 if (_numSensorFailsForNonFunc)
537 {
538 if (!_functional &&
539 (countNonFunctionalSensors() < _numSensorFailsForNonFunc))
540 {
541 updateInventory(true);
542 }
543 }
544 }
545 else
Matt Spinler7d135642021-02-04 12:44:17 -0600546 {
547 getLogger().log(
548 fmt::format("At power on, fan {} is missing", _name));
549
550 if (_fanMissingErrorTimer)
551 {
552 _fanMissingErrorTimer->restartOnce(
553 std::chrono::seconds{*_fanMissingErrorDelay});
554 }
555 }
556 }
557 else
558 {
559 _monitorReady = false;
560
561 if (_monitorTimer.isEnabled())
562 {
563 _monitorTimer.setEnabled(false);
564 }
565
566 if (_fanMissingErrorTimer && _fanMissingErrorTimer->isEnabled())
567 {
568 _fanMissingErrorTimer->setEnabled(false);
569 }
570
571 std::for_each(_sensors.begin(), _sensors.end(), [](auto& sensor) {
572 if (sensor->timerRunning())
573 {
574 sensor->stopTimer();
575 }
576 });
Matt Spinler623635c2021-03-29 13:13:59 -0500577
578 if (_countTimer)
579 {
580 _countTimer->setEnabled(false);
581 }
Matt Spinler7d135642021-02-04 12:44:17 -0600582 }
583#endif
584}
585
Matthew Barth177fe982020-05-26 11:05:19 -0500586} // namespace monitor
587} // namespace fan
588} // namespace phosphor