blob: 5f0414d243b3c99580ae6c304cfa5803d0f7c76f [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),
76 std::get<thresholdField>(s), std::get<timeoutField>(def),
Matt Spinlerfdfcc672021-06-01 14:51:06 -060077 std::get<nonfuncRotorErrDelayField>(def),
78 std::get<countIntervalField>(def), event));
Matthew Barth0a9fe162018-01-26 12:53:15 -060079
Matt Spinler4283c5d2021-03-01 15:56:00 -060080 _trustManager->registerSensor(_sensors.back());
Matthew Barth0a9fe162018-01-26 12:53:15 -060081 }
82
Mike Cappsce6820a2021-05-26 10:40:19 -040083 bool functionalState =
84 (_numSensorFailsForNonFunc == 0) ||
85 (countNonFunctionalSensors() < _numSensorFailsForNonFunc);
86
87 updateInventory(functionalState);
88
Matt Spinlerb0412d02020-10-12 16:53:52 -050089#ifndef MONITOR_USE_JSON
Matthew Barth0a9fe162018-01-26 12:53:15 -060090 // Check current tach state when entering monitor mode
Matthew Barth6ad28432017-08-22 11:18:19 -050091 if (mode != Mode::init)
92 {
Matt Spinlerb0412d02020-10-12 16:53:52 -050093 _monitorReady = true;
94
Matthew Barth177fe982020-05-26 11:05:19 -050095 // The TachSensors will now have already read the input
96 // and target values, so check them.
Matthew Barth6ad28432017-08-22 11:18:19 -050097 tachChanged();
98 }
Matt Spinlerb0412d02020-10-12 16:53:52 -050099#else
Matt Spinler7d135642021-02-04 12:44:17 -0600100 if (_system.isPowerOn())
101 {
102 _monitorTimer.restartOnce(std::chrono::seconds(_monitorDelay));
103 }
Matt Spinlerb0412d02020-10-12 16:53:52 -0500104#endif
Matt Spinlerb63aa092020-10-14 09:45:11 -0500105
Matt Spinler27f6b682020-10-27 08:43:37 -0500106 if (_fanMissingErrorDelay)
107 {
108 _fanMissingErrorTimer = std::make_unique<
109 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
110 event, std::bind(&System::fanMissingErrorTimerExpired, &system,
111 std::ref(*this)));
Matt Spinler7d135642021-02-04 12:44:17 -0600112 }
Matt Spinler27f6b682020-10-27 08:43:37 -0500113
Matt Spinler7d135642021-02-04 12:44:17 -0600114 try
115 {
116 _present = util::SDBusPlus::getProperty<bool>(
117 util::INVENTORY_PATH + _name, util::INV_ITEM_IFACE, "Present");
118
119 if (!_present)
Matt Spinler27f6b682020-10-27 08:43:37 -0500120 {
Matt Spinlerac372972021-01-25 15:11:22 -0600121 getLogger().log(
122 fmt::format("On startup, fan {} is missing", _name));
Matt Spinler7d135642021-02-04 12:44:17 -0600123 if (_system.isPowerOn() && _fanMissingErrorTimer)
124 {
125 _fanMissingErrorTimer->restartOnce(
126 std::chrono::seconds{*_fanMissingErrorDelay});
127 }
128 }
129 }
130 catch (const util::DBusServiceError& e)
131 {
132 // This could happen on the first BMC boot if the presence
133 // detect app hasn't started yet and there isn't an inventory
134 // cache yet.
135 }
136}
137
138void Fan::presenceIfaceAdded(sdbusplus::message::message& msg)
139{
140 sdbusplus::message::object_path path;
141 std::map<std::string, std::map<std::string, std::variant<bool>>> interfaces;
142
143 msg.read(path, interfaces);
144
145 auto properties = interfaces.find(util::INV_ITEM_IFACE);
146 if (properties == interfaces.end())
147 {
148 return;
149 }
150
151 auto property = properties->second.find("Present");
152 if (property == properties->second.end())
153 {
154 return;
155 }
156
157 _present = std::get<bool>(property->second);
158
159 if (!_present)
160 {
161 getLogger().log(fmt::format(
162 "New fan {} interface added and fan is not present", _name));
163 if (_system.isPowerOn() && _fanMissingErrorTimer)
164 {
Matt Spinler27f6b682020-10-27 08:43:37 -0500165 _fanMissingErrorTimer->restartOnce(
166 std::chrono::seconds{*_fanMissingErrorDelay});
167 }
168 }
Matt Spinler7d135642021-02-04 12:44:17 -0600169
170 _system.fanStatusChange(*this);
Matt Spinlerb0412d02020-10-12 16:53:52 -0500171}
172
173void Fan::startMonitor()
174{
175 _monitorReady = true;
176
Matt Spinler4283c5d2021-03-01 15:56:00 -0600177 std::for_each(_sensors.begin(), _sensors.end(), [this](auto& sensor) {
178 if (_present)
179 {
180 try
181 {
182 // Force a getProperty call to check if the tach sensor is
183 // on D-Bus. If it isn't, now set it to nonfunctional.
184 // This isn't done earlier so that code watching for
185 // nonfunctional tach sensors doesn't take actions before
186 // those sensors show up on D-Bus.
187 sensor->updateTachAndTarget();
188 tachChanged(*sensor);
189 }
190 catch (const util::DBusServiceError& e)
191 {
192 // The tach property still isn't on D-Bus, ensure
193 // sensor is nonfunctional.
194 getLogger().log(fmt::format(
195 "Monitoring starting but {} sensor value not on D-Bus",
196 sensor->name()));
197
198 sensor->setFunctional(false);
199
200 if (_numSensorFailsForNonFunc)
201 {
202 if (_functional && (countNonFunctionalSensors() >=
203 _numSensorFailsForNonFunc))
204 {
205 updateInventory(false);
206 }
207 }
208
209 _system.fanStatusChange(*this);
210 }
211 }
212 });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500213}
214
Matt Spinlerebaae612017-04-27 14:21:48 -0500215void Fan::tachChanged()
216{
Matt Spinlerb0412d02020-10-12 16:53:52 -0500217 if (_monitorReady)
Matt Spinlerebaae612017-04-27 14:21:48 -0500218 {
Matt Spinlerb0412d02020-10-12 16:53:52 -0500219 for (auto& s : _sensors)
220 {
221 tachChanged(*s);
222 }
Matt Spinlerebaae612017-04-27 14:21:48 -0500223 }
224}
225
Matt Spinlerebaae612017-04-27 14:21:48 -0500226void Fan::tachChanged(TachSensor& sensor)
227{
Matt Spinler7d135642021-02-04 12:44:17 -0600228 if (!_system.isPowerOn() || !_monitorReady)
229 {
230 return;
231 }
232
Matt Spinlerc39e8592017-09-28 13:13:08 -0500233 if (_trustManager->active())
234 {
235 if (!_trustManager->checkTrust(sensor))
236 {
237 return;
238 }
239 }
240
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600241 // If the error checking method is 'count', if a tach change leads
242 // to an out of range sensor the count timer will take over in calling
243 // process() until the sensor is healthy again.
244 if (!sensor.countTimerRunning())
Matt Spinler623635c2021-03-29 13:13:59 -0500245 {
246 process(sensor);
247 }
248}
249
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600250void Fan::countTimerExpired(TachSensor& sensor)
Matt Spinler623635c2021-03-29 13:13:59 -0500251{
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600252 if (_trustManager->active() && !_trustManager->checkTrust(sensor))
Matt Spinler623635c2021-03-29 13:13:59 -0500253 {
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600254 return;
Matt Spinler623635c2021-03-29 13:13:59 -0500255 }
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600256 process(sensor);
Matthew Barthfcb0dbc2021-02-10 14:23:39 -0600257}
258
259void Fan::process(TachSensor& sensor)
260{
Matthew Barth177fe982020-05-26 11:05:19 -0500261 // If this sensor is out of range at this moment, start
262 // its timer, at the end of which the inventory
263 // for the fan may get updated to not functional.
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500264
Matthew Barth177fe982020-05-26 11:05:19 -0500265 // If this sensor is OK, put everything back into a good state.
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500266
267 if (outOfRange(sensor))
268 {
Matthew Barthe11cbc62018-02-20 12:11:07 -0600269 if (sensor.functional())
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500270 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800271 switch (sensor.getMethod())
272 {
273 case MethodMode::timebased:
274 // Start nonfunctional timer if not already running
275 sensor.startTimer(TimerMode::nonfunc);
276 break;
277 case MethodMode::count:
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600278
279 if (!sensor.countTimerRunning())
280 {
281 sensor.startCountTimer();
282 }
Jolie Ku69f2f482020-10-21 09:59:43 +0800283 sensor.setCounter(true);
284 if (sensor.getCounter() >= sensor.getThreshold())
285 {
286 updateState(sensor);
287 }
288 break;
289 }
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500290 }
291 }
292 else
293 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800294 switch (sensor.getMethod())
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500295 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800296 case MethodMode::timebased:
297 if (sensor.functional())
298 {
Matthew Barth11b5d8f2021-01-28 14:04:09 -0600299 if (sensor.timerRunning())
300 {
301 sensor.stopTimer();
302 }
Jolie Ku69f2f482020-10-21 09:59:43 +0800303 }
304 else
305 {
306 // Start functional timer if not already running
307 sensor.startTimer(TimerMode::func);
308 }
309 break;
310 case MethodMode::count:
311 sensor.setCounter(false);
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600312 if (sensor.getCounter() == 0)
Jolie Ku69f2f482020-10-21 09:59:43 +0800313 {
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600314 if (!sensor.functional())
315 {
316 updateState(sensor);
317 }
318
319 sensor.stopCountTimer();
Jolie Ku69f2f482020-10-21 09:59:43 +0800320 }
321 break;
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500322 }
323 }
Matt Spinlerebaae612017-04-27 14:21:48 -0500324}
325
Matthew Barthf552ea52018-01-15 16:22:04 -0600326uint64_t Fan::findTargetSpeed()
Matt Spinlerabf8da32017-04-27 14:08:45 -0500327{
328 uint64_t target = 0;
Matthew Barth177fe982020-05-26 11:05:19 -0500329 // The sensor doesn't support a target,
330 // so get it from another sensor.
Matthew Barthf552ea52018-01-15 16:22:04 -0600331 auto s = std::find_if(_sensors.begin(), _sensors.end(),
Matthew Barth177fe982020-05-26 11:05:19 -0500332 [](const auto& s) { return s->hasTarget(); });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500333
Matthew Barthf552ea52018-01-15 16:22:04 -0600334 if (s != _sensors.end())
Matt Spinlerabf8da32017-04-27 14:08:45 -0500335 {
Matthew Barthf552ea52018-01-15 16:22:04 -0600336 target = (*s)->getTarget();
Matt Spinlerabf8da32017-04-27 14:08:45 -0500337 }
338
339 return target;
340}
341
Mike Cappsce6820a2021-05-26 10:40:19 -0400342size_t Fan::countNonFunctionalSensors() const
Matt Spinlerabf8da32017-04-27 14:08:45 -0500343{
Matthew Barth7c23a042021-01-26 16:21:45 -0600344 return std::count_if(_sensors.begin(), _sensors.end(),
345 [](const auto& s) { return !s->functional(); });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500346}
347
Matt Spinlerabf8da32017-04-27 14:08:45 -0500348bool Fan::outOfRange(const TachSensor& sensor)
349{
350 auto actual = static_cast<uint64_t>(sensor.getInput());
Matthew Barth7c23a042021-01-26 16:21:45 -0600351 auto range = sensor.getRange(_deviation);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500352
Matthew Barth7c23a042021-01-26 16:21:45 -0600353 if ((actual < range.first) || (actual > range.second))
Matt Spinlerabf8da32017-04-27 14:08:45 -0500354 {
355 return true;
356 }
357
358 return false;
359}
360
Jolie Ku69f2f482020-10-21 09:59:43 +0800361void Fan::updateState(TachSensor& sensor)
Matt Spinlera9406a72017-04-27 14:29:24 -0500362{
Matthew Barth7c23a042021-01-26 16:21:45 -0600363 auto range = sensor.getRange(_deviation);
Matt Spinler7d135642021-02-04 12:44:17 -0600364
365 if (!_system.isPowerOn())
366 {
367 return;
368 }
369
Matthew Barthe11cbc62018-02-20 12:11:07 -0600370 sensor.setFunctional(!sensor.functional());
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500371 getLogger().log(
372 fmt::format("Setting tach sensor {} functional state to {}. "
Matthew Barth7c23a042021-01-26 16:21:45 -0600373 "[target = {}, input = {}, allowed range = ({} - {})]",
374 sensor.name(), sensor.functional(), sensor.getTarget(),
375 sensor.getInput(), range.first, range.second));
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500376
377 // A zero value for _numSensorFailsForNonFunc means we aren't dealing
378 // with fan FRU functional status, only sensor functional status.
379 if (_numSensorFailsForNonFunc)
Matthew Barthe11cbc62018-02-20 12:11:07 -0600380 {
Matthew Barth7c23a042021-01-26 16:21:45 -0600381 auto numNonFuncSensors = countNonFunctionalSensors();
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500382 // If the fan was nonfunctional and enough sensors are now OK,
Matthew Barthcceffdd2021-05-20 12:17:21 -0500383 // the fan can be set to functional as long as `set_func_on_present` was
384 // not set
385 if (!_setFuncOnPresent && !_functional &&
386 !(numNonFuncSensors >= _numSensorFailsForNonFunc))
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500387 {
Matthew Barth7c23a042021-01-26 16:21:45 -0600388 getLogger().log(fmt::format("Setting fan {} to functional, number "
389 "of nonfunctional sensors = {}",
390 _name, numNonFuncSensors));
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500391 updateInventory(true);
392 }
Matt Spinlera9406a72017-04-27 14:29:24 -0500393
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500394 // If the fan is currently functional, but too many
395 // contained sensors are now nonfunctional, update
Matthew Barth7c23a042021-01-26 16:21:45 -0600396 // the fan to nonfunctional.
397 if (_functional && (numNonFuncSensors >= _numSensorFailsForNonFunc))
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500398 {
Matthew Barth7c23a042021-01-26 16:21:45 -0600399 getLogger().log(fmt::format("Setting fan {} to nonfunctional, "
400 "number of nonfunctional sensors = {}",
401 _name, numNonFuncSensors));
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500402 updateInventory(false);
403 }
Matt Spinlerb1e18512017-04-27 14:42:33 -0500404 }
Matt Spinlerb63aa092020-10-14 09:45:11 -0500405
406 _system.fanStatusChange(*this);
Matt Spinlera9406a72017-04-27 14:29:24 -0500407}
408
Matt Spinlerb1e18512017-04-27 14:42:33 -0500409void Fan::updateInventory(bool functional)
410{
Matthew Barth177fe982020-05-26 11:05:19 -0500411 auto objectMap =
412 util::getObjMap<bool>(_name, util::OPERATIONAL_STATUS_INTF,
413 util::FUNCTIONAL_PROPERTY, functional);
Matthew Barth51dd1852017-11-16 15:21:13 -0600414 auto response = util::SDBusPlus::lookupAndCallMethod(
Matthew Barth177fe982020-05-26 11:05:19 -0500415 _bus, util::INVENTORY_PATH, util::INVENTORY_INTF, "Notify", objectMap);
Matt Spinlerb1e18512017-04-27 14:42:33 -0500416 if (response.is_method_error())
417 {
418 log<level::ERR>("Error in Notify call to update inventory");
419 return;
420 }
421
Matthew Barth177fe982020-05-26 11:05:19 -0500422 // This will always track the current state of the inventory.
Matt Spinlerb1e18512017-04-27 14:42:33 -0500423 _functional = functional;
424}
425
Matt Spinlerb63aa092020-10-14 09:45:11 -0500426void Fan::presenceChanged(sdbusplus::message::message& msg)
427{
428 std::string interface;
429 std::map<std::string, std::variant<bool>> properties;
430
431 msg.read(interface, properties);
432
433 auto presentProp = properties.find("Present");
434 if (presentProp != properties.end())
435 {
436 _present = std::get<bool>(presentProp->second);
437
Matt Spinler27f6b682020-10-27 08:43:37 -0500438 getLogger().log(
Matt Spinlerac372972021-01-25 15:11:22 -0600439 fmt::format("Fan {} presence state change to {}", _name, _present));
Matt Spinler27f6b682020-10-27 08:43:37 -0500440
Matt Spinlerb63aa092020-10-14 09:45:11 -0500441 _system.fanStatusChange(*this);
Matt Spinler27f6b682020-10-27 08:43:37 -0500442
Matt Spinlera3584bd2021-03-29 15:48:30 -0500443 if (_present && _setFuncOnPresent)
444 {
445 updateInventory(true);
446 std::for_each(_sensors.begin(), _sensors.end(), [](auto& sensor) {
447 sensor->setFunctional(true);
448 sensor->resetMethod();
449 });
450 }
451
Matt Spinler27f6b682020-10-27 08:43:37 -0500452 if (_fanMissingErrorDelay)
453 {
Matt Spinler7d135642021-02-04 12:44:17 -0600454 if (!_present && _system.isPowerOn())
Matt Spinler27f6b682020-10-27 08:43:37 -0500455 {
456 _fanMissingErrorTimer->restartOnce(
457 std::chrono::seconds{*_fanMissingErrorDelay});
458 }
Matt Spinler7d135642021-02-04 12:44:17 -0600459 else if (_present && _fanMissingErrorTimer->isEnabled())
Matt Spinler27f6b682020-10-27 08:43:37 -0500460 {
461 _fanMissingErrorTimer->setEnabled(false);
462 }
463 }
Matt Spinlerb63aa092020-10-14 09:45:11 -0500464 }
465}
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500466
467void Fan::sensorErrorTimerExpired(const TachSensor& sensor)
468{
Matt Spinler7d135642021-02-04 12:44:17 -0600469 if (_present && _system.isPowerOn())
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500470 {
471 _system.sensorErrorTimerExpired(*this, sensor);
472 }
473}
474
Matt Spinler7d135642021-02-04 12:44:17 -0600475void Fan::powerStateChanged(bool powerStateOn)
476{
477#ifdef MONITOR_USE_JSON
478 if (powerStateOn)
479 {
Matt Spinler7d135642021-02-04 12:44:17 -0600480 _monitorTimer.restartOnce(std::chrono::seconds(_monitorDelay));
481
Matt Spinlerbb449c12021-06-14 11:45:28 -0600482 _numSensorsOnDBusAtPowerOn = 0;
483
484 std::for_each(_sensors.begin(), _sensors.end(), [this](auto& sensor) {
485 try
486 {
487 // Force a getProperty call. If sensor is on D-Bus,
488 // then make sure it's functional.
489 sensor->updateTachAndTarget();
490
491 _numSensorsOnDBusAtPowerOn++;
492
493 if (_present)
494 {
495 // If not functional, set it back to functional.
496 if (!sensor->functional())
497 {
498 sensor->setFunctional(true);
499 _system.fanStatusChange(*this, true);
500 }
501
502 // Set the counters back to zero
503 if (sensor->getMethod() == MethodMode::count)
504 {
505 sensor->resetMethod();
506 }
507 }
508 }
509 catch (const util::DBusError& e)
510 {
511 // Properties still aren't on D-Bus. Let startMonitor()
512 // deal with it, or maybe System::powerStateChanged() if
513 // there aren't any sensors at all on D-Bus.
514 getLogger().log(fmt::format(
515 "At power on, tach sensor {} value not on D-Bus",
516 sensor->name()));
517 }
518 });
519
Matt Spinler4283c5d2021-03-01 15:56:00 -0600520 if (_present)
521 {
Matt Spinler4283c5d2021-03-01 15:56:00 -0600522 // 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 }
Matt Spinler623635c2021-03-29 13:13:59 -0500564
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600565 sensor->stopCountTimer();
566 });
Matt Spinler7d135642021-02-04 12:44:17 -0600567 }
568#endif
569}
570
Matthew Barth177fe982020-05-26 11:05:19 -0500571} // namespace monitor
572} // namespace fan
573} // namespace phosphor