blob: c5322b1b9a19513fbaf3cc4f6679820d2dd3572d [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
Mike Capps9ff48772021-07-19 14:49:43 -040087 if (updateInventory(functionalState) && !functionalState)
88 {
89 // the inventory update threw an exception, possibly because D-Bus
90 // wasn't ready. Try to update sensors back to functional to avoid a
91 // false-alarm. They will be updated again from subscribing to the
92 // properties-changed event
93
94 for (auto& sensor : _sensors)
95 sensor->setFunctional(true);
96 }
Mike Cappsce6820a2021-05-26 10:40:19 -040097
Matt Spinlerb0412d02020-10-12 16:53:52 -050098#ifndef MONITOR_USE_JSON
Matthew Barth0a9fe162018-01-26 12:53:15 -060099 // Check current tach state when entering monitor mode
Matthew Barth6ad28432017-08-22 11:18:19 -0500100 if (mode != Mode::init)
101 {
Matt Spinlerb0412d02020-10-12 16:53:52 -0500102 _monitorReady = true;
103
Matthew Barth177fe982020-05-26 11:05:19 -0500104 // The TachSensors will now have already read the input
105 // and target values, so check them.
Matthew Barth6ad28432017-08-22 11:18:19 -0500106 tachChanged();
107 }
Matt Spinlerb0412d02020-10-12 16:53:52 -0500108#else
Matt Spinler7d135642021-02-04 12:44:17 -0600109 if (_system.isPowerOn())
110 {
111 _monitorTimer.restartOnce(std::chrono::seconds(_monitorDelay));
112 }
Matt Spinlerb0412d02020-10-12 16:53:52 -0500113#endif
Matt Spinlerb63aa092020-10-14 09:45:11 -0500114
Matt Spinler27f6b682020-10-27 08:43:37 -0500115 if (_fanMissingErrorDelay)
116 {
117 _fanMissingErrorTimer = std::make_unique<
118 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
119 event, std::bind(&System::fanMissingErrorTimerExpired, &system,
120 std::ref(*this)));
Matt Spinler7d135642021-02-04 12:44:17 -0600121 }
Matt Spinler27f6b682020-10-27 08:43:37 -0500122
Matt Spinler7d135642021-02-04 12:44:17 -0600123 try
124 {
125 _present = util::SDBusPlus::getProperty<bool>(
126 util::INVENTORY_PATH + _name, util::INV_ITEM_IFACE, "Present");
127
128 if (!_present)
Matt Spinler27f6b682020-10-27 08:43:37 -0500129 {
Matt Spinlerac372972021-01-25 15:11:22 -0600130 getLogger().log(
131 fmt::format("On startup, fan {} is missing", _name));
Matt Spinler7d135642021-02-04 12:44:17 -0600132 if (_system.isPowerOn() && _fanMissingErrorTimer)
133 {
134 _fanMissingErrorTimer->restartOnce(
135 std::chrono::seconds{*_fanMissingErrorDelay});
136 }
137 }
138 }
139 catch (const util::DBusServiceError& e)
140 {
141 // This could happen on the first BMC boot if the presence
142 // detect app hasn't started yet and there isn't an inventory
143 // cache yet.
144 }
145}
146
147void Fan::presenceIfaceAdded(sdbusplus::message::message& msg)
148{
149 sdbusplus::message::object_path path;
150 std::map<std::string, std::map<std::string, std::variant<bool>>> interfaces;
151
152 msg.read(path, interfaces);
153
154 auto properties = interfaces.find(util::INV_ITEM_IFACE);
155 if (properties == interfaces.end())
156 {
157 return;
158 }
159
160 auto property = properties->second.find("Present");
161 if (property == properties->second.end())
162 {
163 return;
164 }
165
166 _present = std::get<bool>(property->second);
167
168 if (!_present)
169 {
170 getLogger().log(fmt::format(
171 "New fan {} interface added and fan is not present", _name));
172 if (_system.isPowerOn() && _fanMissingErrorTimer)
173 {
Matt Spinler27f6b682020-10-27 08:43:37 -0500174 _fanMissingErrorTimer->restartOnce(
175 std::chrono::seconds{*_fanMissingErrorDelay});
176 }
177 }
Matt Spinler7d135642021-02-04 12:44:17 -0600178
179 _system.fanStatusChange(*this);
Matt Spinlerb0412d02020-10-12 16:53:52 -0500180}
181
182void Fan::startMonitor()
183{
184 _monitorReady = true;
185
Matt Spinler4283c5d2021-03-01 15:56:00 -0600186 std::for_each(_sensors.begin(), _sensors.end(), [this](auto& sensor) {
187 if (_present)
188 {
189 try
190 {
191 // Force a getProperty call to check if the tach sensor is
192 // on D-Bus. If it isn't, now set it to nonfunctional.
193 // This isn't done earlier so that code watching for
194 // nonfunctional tach sensors doesn't take actions before
195 // those sensors show up on D-Bus.
196 sensor->updateTachAndTarget();
197 tachChanged(*sensor);
198 }
199 catch (const util::DBusServiceError& e)
200 {
201 // The tach property still isn't on D-Bus, ensure
202 // sensor is nonfunctional.
203 getLogger().log(fmt::format(
204 "Monitoring starting but {} sensor value not on D-Bus",
205 sensor->name()));
206
207 sensor->setFunctional(false);
208
209 if (_numSensorFailsForNonFunc)
210 {
211 if (_functional && (countNonFunctionalSensors() >=
212 _numSensorFailsForNonFunc))
213 {
214 updateInventory(false);
215 }
216 }
217
218 _system.fanStatusChange(*this);
219 }
220 }
221 });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500222}
223
Matt Spinlerebaae612017-04-27 14:21:48 -0500224void Fan::tachChanged()
225{
Matt Spinlerb0412d02020-10-12 16:53:52 -0500226 if (_monitorReady)
Matt Spinlerebaae612017-04-27 14:21:48 -0500227 {
Matt Spinlerb0412d02020-10-12 16:53:52 -0500228 for (auto& s : _sensors)
229 {
230 tachChanged(*s);
231 }
Matt Spinlerebaae612017-04-27 14:21:48 -0500232 }
233}
234
Matt Spinlerebaae612017-04-27 14:21:48 -0500235void Fan::tachChanged(TachSensor& sensor)
236{
Matt Spinler7d135642021-02-04 12:44:17 -0600237 if (!_system.isPowerOn() || !_monitorReady)
238 {
239 return;
240 }
241
Matt Spinlerc39e8592017-09-28 13:13:08 -0500242 if (_trustManager->active())
243 {
244 if (!_trustManager->checkTrust(sensor))
245 {
246 return;
247 }
248 }
249
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600250 // If the error checking method is 'count', if a tach change leads
251 // to an out of range sensor the count timer will take over in calling
252 // process() until the sensor is healthy again.
253 if (!sensor.countTimerRunning())
Matt Spinler623635c2021-03-29 13:13:59 -0500254 {
255 process(sensor);
256 }
257}
258
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600259void Fan::countTimerExpired(TachSensor& sensor)
Matt Spinler623635c2021-03-29 13:13:59 -0500260{
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600261 if (_trustManager->active() && !_trustManager->checkTrust(sensor))
Matt Spinler623635c2021-03-29 13:13:59 -0500262 {
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600263 return;
Matt Spinler623635c2021-03-29 13:13:59 -0500264 }
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600265 process(sensor);
Matthew Barthfcb0dbc2021-02-10 14:23:39 -0600266}
267
268void Fan::process(TachSensor& sensor)
269{
Matthew Barth177fe982020-05-26 11:05:19 -0500270 // If this sensor is out of range at this moment, start
271 // its timer, at the end of which the inventory
272 // for the fan may get updated to not functional.
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500273
Matthew Barth177fe982020-05-26 11:05:19 -0500274 // If this sensor is OK, put everything back into a good state.
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500275
276 if (outOfRange(sensor))
277 {
Matthew Barthe11cbc62018-02-20 12:11:07 -0600278 if (sensor.functional())
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500279 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800280 switch (sensor.getMethod())
281 {
282 case MethodMode::timebased:
283 // Start nonfunctional timer if not already running
284 sensor.startTimer(TimerMode::nonfunc);
285 break;
286 case MethodMode::count:
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600287
288 if (!sensor.countTimerRunning())
289 {
290 sensor.startCountTimer();
291 }
Jolie Ku69f2f482020-10-21 09:59:43 +0800292 sensor.setCounter(true);
293 if (sensor.getCounter() >= sensor.getThreshold())
294 {
295 updateState(sensor);
296 }
297 break;
298 }
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500299 }
300 }
301 else
302 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800303 switch (sensor.getMethod())
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500304 {
Jolie Ku69f2f482020-10-21 09:59:43 +0800305 case MethodMode::timebased:
306 if (sensor.functional())
307 {
Matthew Barth11b5d8f2021-01-28 14:04:09 -0600308 if (sensor.timerRunning())
309 {
310 sensor.stopTimer();
311 }
Jolie Ku69f2f482020-10-21 09:59:43 +0800312 }
313 else
314 {
315 // Start functional timer if not already running
316 sensor.startTimer(TimerMode::func);
317 }
318 break;
319 case MethodMode::count:
320 sensor.setCounter(false);
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600321 if (sensor.getCounter() == 0)
Jolie Ku69f2f482020-10-21 09:59:43 +0800322 {
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600323 if (!sensor.functional())
324 {
325 updateState(sensor);
326 }
327
328 sensor.stopCountTimer();
Jolie Ku69f2f482020-10-21 09:59:43 +0800329 }
330 break;
Matt Spinlera4c8f1f2017-04-27 14:38:38 -0500331 }
332 }
Matt Spinlerebaae612017-04-27 14:21:48 -0500333}
334
Matthew Barthf552ea52018-01-15 16:22:04 -0600335uint64_t Fan::findTargetSpeed()
Matt Spinlerabf8da32017-04-27 14:08:45 -0500336{
337 uint64_t target = 0;
Matthew Barth177fe982020-05-26 11:05:19 -0500338 // The sensor doesn't support a target,
339 // so get it from another sensor.
Matthew Barthf552ea52018-01-15 16:22:04 -0600340 auto s = std::find_if(_sensors.begin(), _sensors.end(),
Matthew Barth177fe982020-05-26 11:05:19 -0500341 [](const auto& s) { return s->hasTarget(); });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500342
Matthew Barthf552ea52018-01-15 16:22:04 -0600343 if (s != _sensors.end())
Matt Spinlerabf8da32017-04-27 14:08:45 -0500344 {
Matthew Barthf552ea52018-01-15 16:22:04 -0600345 target = (*s)->getTarget();
Matt Spinlerabf8da32017-04-27 14:08:45 -0500346 }
347
348 return target;
349}
350
Mike Cappsce6820a2021-05-26 10:40:19 -0400351size_t Fan::countNonFunctionalSensors() const
Matt Spinlerabf8da32017-04-27 14:08:45 -0500352{
Matthew Barth7c23a042021-01-26 16:21:45 -0600353 return std::count_if(_sensors.begin(), _sensors.end(),
354 [](const auto& s) { return !s->functional(); });
Matt Spinlerabf8da32017-04-27 14:08:45 -0500355}
356
Matt Spinlerabf8da32017-04-27 14:08:45 -0500357bool Fan::outOfRange(const TachSensor& sensor)
358{
359 auto actual = static_cast<uint64_t>(sensor.getInput());
Matthew Barth7c23a042021-01-26 16:21:45 -0600360 auto range = sensor.getRange(_deviation);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500361
Matthew Barth7c23a042021-01-26 16:21:45 -0600362 if ((actual < range.first) || (actual > range.second))
Matt Spinlerabf8da32017-04-27 14:08:45 -0500363 {
364 return true;
365 }
366
367 return false;
368}
369
Jolie Ku69f2f482020-10-21 09:59:43 +0800370void Fan::updateState(TachSensor& sensor)
Matt Spinlera9406a72017-04-27 14:29:24 -0500371{
Matthew Barth7c23a042021-01-26 16:21:45 -0600372 auto range = sensor.getRange(_deviation);
Matt Spinler7d135642021-02-04 12:44:17 -0600373
374 if (!_system.isPowerOn())
375 {
376 return;
377 }
378
Matthew Barthe11cbc62018-02-20 12:11:07 -0600379 sensor.setFunctional(!sensor.functional());
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500380 getLogger().log(
381 fmt::format("Setting tach sensor {} functional state to {}. "
Matthew Barth7c23a042021-01-26 16:21:45 -0600382 "[target = {}, input = {}, allowed range = ({} - {})]",
383 sensor.name(), sensor.functional(), sensor.getTarget(),
384 sensor.getInput(), range.first, range.second));
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500385
386 // A zero value for _numSensorFailsForNonFunc means we aren't dealing
387 // with fan FRU functional status, only sensor functional status.
388 if (_numSensorFailsForNonFunc)
Matthew Barthe11cbc62018-02-20 12:11:07 -0600389 {
Matthew Barth7c23a042021-01-26 16:21:45 -0600390 auto numNonFuncSensors = countNonFunctionalSensors();
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500391 // If the fan was nonfunctional and enough sensors are now OK,
Matthew Barthcceffdd2021-05-20 12:17:21 -0500392 // the fan can be set to functional as long as `set_func_on_present` was
393 // not set
394 if (!_setFuncOnPresent && !_functional &&
395 !(numNonFuncSensors >= _numSensorFailsForNonFunc))
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500396 {
Matthew Barth7c23a042021-01-26 16:21:45 -0600397 getLogger().log(fmt::format("Setting fan {} to functional, number "
398 "of nonfunctional sensors = {}",
399 _name, numNonFuncSensors));
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500400 updateInventory(true);
401 }
Matt Spinlera9406a72017-04-27 14:29:24 -0500402
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500403 // If the fan is currently functional, but too many
404 // contained sensors are now nonfunctional, update
Matthew Barth7c23a042021-01-26 16:21:45 -0600405 // the fan to nonfunctional.
406 if (_functional && (numNonFuncSensors >= _numSensorFailsForNonFunc))
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500407 {
Matthew Barth7c23a042021-01-26 16:21:45 -0600408 getLogger().log(fmt::format("Setting fan {} to nonfunctional, "
409 "number of nonfunctional sensors = {}",
410 _name, numNonFuncSensors));
Matt Spinlerae1f8ef2020-10-14 16:15:51 -0500411 updateInventory(false);
412 }
Matt Spinlerb1e18512017-04-27 14:42:33 -0500413 }
Matt Spinlerb63aa092020-10-14 09:45:11 -0500414
415 _system.fanStatusChange(*this);
Matt Spinlera9406a72017-04-27 14:29:24 -0500416}
417
Mike Capps9ff48772021-07-19 14:49:43 -0400418bool Fan::updateInventory(bool functional)
Matt Spinlerb1e18512017-04-27 14:42:33 -0500419{
Mike Capps9ff48772021-07-19 14:49:43 -0400420 bool dbusError = false;
421
422 try
Matt Spinlerb1e18512017-04-27 14:42:33 -0500423 {
Mike Capps9ff48772021-07-19 14:49:43 -0400424 auto objectMap =
425 util::getObjMap<bool>(_name, util::OPERATIONAL_STATUS_INTF,
426 util::FUNCTIONAL_PROPERTY, functional);
427
428 auto response = util::SDBusPlus::lookupAndCallMethod(
429 _bus, util::INVENTORY_PATH, util::INVENTORY_INTF, "Notify",
430 objectMap);
431
432 if (response.is_method_error())
433 {
434 log<level::ERR>("Error in Notify call to update inventory");
435
436 dbusError = true;
437 }
438 }
439 catch (const util::DBusError& e)
440 {
441 dbusError = true;
442
443 getLogger().log(
444 fmt::format("D-Bus Exception reading/updating inventory : {}",
445 e.what()),
446 Logger::error);
Matt Spinlerb1e18512017-04-27 14:42:33 -0500447 }
448
Matthew Barth177fe982020-05-26 11:05:19 -0500449 // This will always track the current state of the inventory.
Matt Spinlerb1e18512017-04-27 14:42:33 -0500450 _functional = functional;
Mike Capps9ff48772021-07-19 14:49:43 -0400451
452 return dbusError;
Matt Spinlerb1e18512017-04-27 14:42:33 -0500453}
454
Matt Spinlerb63aa092020-10-14 09:45:11 -0500455void Fan::presenceChanged(sdbusplus::message::message& msg)
456{
457 std::string interface;
458 std::map<std::string, std::variant<bool>> properties;
459
460 msg.read(interface, properties);
461
462 auto presentProp = properties.find("Present");
463 if (presentProp != properties.end())
464 {
465 _present = std::get<bool>(presentProp->second);
466
Matt Spinler27f6b682020-10-27 08:43:37 -0500467 getLogger().log(
Matt Spinlerac372972021-01-25 15:11:22 -0600468 fmt::format("Fan {} presence state change to {}", _name, _present));
Matt Spinler27f6b682020-10-27 08:43:37 -0500469
Matt Spinlerb63aa092020-10-14 09:45:11 -0500470 _system.fanStatusChange(*this);
Matt Spinler27f6b682020-10-27 08:43:37 -0500471
Matt Spinlera3584bd2021-03-29 15:48:30 -0500472 if (_present && _setFuncOnPresent)
473 {
474 updateInventory(true);
475 std::for_each(_sensors.begin(), _sensors.end(), [](auto& sensor) {
476 sensor->setFunctional(true);
477 sensor->resetMethod();
478 });
479 }
480
Matt Spinler27f6b682020-10-27 08:43:37 -0500481 if (_fanMissingErrorDelay)
482 {
Matt Spinler7d135642021-02-04 12:44:17 -0600483 if (!_present && _system.isPowerOn())
Matt Spinler27f6b682020-10-27 08:43:37 -0500484 {
485 _fanMissingErrorTimer->restartOnce(
486 std::chrono::seconds{*_fanMissingErrorDelay});
487 }
Matt Spinler7d135642021-02-04 12:44:17 -0600488 else if (_present && _fanMissingErrorTimer->isEnabled())
Matt Spinler27f6b682020-10-27 08:43:37 -0500489 {
490 _fanMissingErrorTimer->setEnabled(false);
491 }
492 }
Matt Spinlerb63aa092020-10-14 09:45:11 -0500493 }
494}
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500495
496void Fan::sensorErrorTimerExpired(const TachSensor& sensor)
497{
Matt Spinler7d135642021-02-04 12:44:17 -0600498 if (_present && _system.isPowerOn())
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500499 {
500 _system.sensorErrorTimerExpired(*this, sensor);
501 }
502}
503
Matt Spinler7d135642021-02-04 12:44:17 -0600504void Fan::powerStateChanged(bool powerStateOn)
505{
506#ifdef MONITOR_USE_JSON
507 if (powerStateOn)
508 {
Matt Spinler7d135642021-02-04 12:44:17 -0600509 _monitorTimer.restartOnce(std::chrono::seconds(_monitorDelay));
510
Matt Spinlerbb449c12021-06-14 11:45:28 -0600511 _numSensorsOnDBusAtPowerOn = 0;
512
513 std::for_each(_sensors.begin(), _sensors.end(), [this](auto& sensor) {
514 try
515 {
516 // Force a getProperty call. If sensor is on D-Bus,
517 // then make sure it's functional.
518 sensor->updateTachAndTarget();
519
520 _numSensorsOnDBusAtPowerOn++;
521
522 if (_present)
523 {
524 // If not functional, set it back to functional.
525 if (!sensor->functional())
526 {
527 sensor->setFunctional(true);
528 _system.fanStatusChange(*this, true);
529 }
530
531 // Set the counters back to zero
532 if (sensor->getMethod() == MethodMode::count)
533 {
534 sensor->resetMethod();
535 }
536 }
537 }
538 catch (const util::DBusError& e)
539 {
540 // Properties still aren't on D-Bus. Let startMonitor()
541 // deal with it, or maybe System::powerStateChanged() if
542 // there aren't any sensors at all on D-Bus.
543 getLogger().log(fmt::format(
544 "At power on, tach sensor {} value not on D-Bus",
545 sensor->name()));
546 }
547 });
548
Matt Spinler4283c5d2021-03-01 15:56:00 -0600549 if (_present)
550 {
Matt Spinler4283c5d2021-03-01 15:56:00 -0600551 // If configured to change functional state on the fan itself,
552 // Set it back to true now if necessary.
553 if (_numSensorFailsForNonFunc)
554 {
555 if (!_functional &&
556 (countNonFunctionalSensors() < _numSensorFailsForNonFunc))
557 {
558 updateInventory(true);
559 }
560 }
561 }
562 else
Matt Spinler7d135642021-02-04 12:44:17 -0600563 {
564 getLogger().log(
565 fmt::format("At power on, fan {} is missing", _name));
566
567 if (_fanMissingErrorTimer)
568 {
569 _fanMissingErrorTimer->restartOnce(
570 std::chrono::seconds{*_fanMissingErrorDelay});
571 }
572 }
573 }
574 else
575 {
576 _monitorReady = false;
577
578 if (_monitorTimer.isEnabled())
579 {
580 _monitorTimer.setEnabled(false);
581 }
582
583 if (_fanMissingErrorTimer && _fanMissingErrorTimer->isEnabled())
584 {
585 _fanMissingErrorTimer->setEnabled(false);
586 }
587
588 std::for_each(_sensors.begin(), _sensors.end(), [](auto& sensor) {
589 if (sensor->timerRunning())
590 {
591 sensor->stopTimer();
592 }
Matt Spinler623635c2021-03-29 13:13:59 -0500593
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600594 sensor->stopCountTimer();
595 });
Matt Spinler7d135642021-02-04 12:44:17 -0600596 }
597#endif
598}
599
Matthew Barth177fe982020-05-26 11:05:19 -0500600} // namespace monitor
601} // namespace fan
602} // namespace phosphor