blob: b671467cb51cdfcef49d61a58b841e8b0910fbbe [file] [log] [blame]
Matthew Barthbf7b7b12017-03-07 15:46:59 -06001#pragma once
2
3#include <experimental/filesystem>
Matt Spinlerb4e65572017-10-17 10:09:18 -05004#include <phosphor-logging/elog-errors.hpp>
5#include <phosphor-logging/log.hpp>
6#include <xyz/openbmc_project/Sensor/Device/error.hpp>
Matthew Barth048ac872017-03-09 14:36:08 -06007#include "fan_speed.hpp"
Patrick Venture9331ab72018-01-29 09:48:47 -08008#include "fan_pwm.hpp"
Matthew Barthbf7b7b12017-03-07 15:46:59 -06009
10/** @class Targets
11 * @brief Target type traits.
12 *
13 * @tparam T - The target type.
14 */
15template <typename T>
16struct Targets
17{
18 static void fail()
19 {
20 static_assert(sizeof(Targets) == -1, "Unsupported Target type");
21 }
22};
23
24/**@brief Targets specialization for fan speed. */
25template <>
Matthew Barth048ac872017-03-09 14:36:08 -060026struct Targets<hwmon::FanSpeed>
Matthew Barthbf7b7b12017-03-07 15:46:59 -060027{
28 static constexpr InterfaceType type = InterfaceType::FAN_SPEED;
Matthew Barthbf7b7b12017-03-07 15:46:59 -060029};
30
Patrick Venture9331ab72018-01-29 09:48:47 -080031template <>
32struct Targets<hwmon::FanPwm>
33{
34 static constexpr InterfaceType type = InterfaceType::FAN_PWM;
35};
36
Matthew Barthbf7b7b12017-03-07 15:46:59 -060037/** @brief addTarget
38 *
39 * Creates the target type interface
40 *
41 * @tparam T - The target type
42 *
43 * @param[in] sensor - A sensor type and name
Matt Spinlerb4e65572017-10-17 10:09:18 -050044 * @param[in] ioAccess - hwmon sysfs access object
45 * @param[in] devPath - The /sys/devices sysfs path
Matthew Barthbf7b7b12017-03-07 15:46:59 -060046 * @param[in] info - The sdbusplus server connection and interfaces
Matt Spinler0a8de642017-05-11 10:59:39 -050047 *
48 * @return A shared pointer to the target interface object
49 * Will be empty if no interface was created
Matthew Barthbf7b7b12017-03-07 15:46:59 -060050 */
51template <typename T>
Matt Spinler0a8de642017-05-11 10:59:39 -050052std::shared_ptr<T> addTarget(const SensorSet::key_type& sensor,
Matt Spinlerb4e65572017-10-17 10:09:18 -050053 const sysfs::hwmonio::HwmonIO& ioAccess,
Brad Bishop751043e2017-08-29 11:13:46 -040054 const std::string& devPath,
Matt Spinler0a8de642017-05-11 10:59:39 -050055 ObjectInfo& info)
Matthew Barthbf7b7b12017-03-07 15:46:59 -060056{
Matt Spinler0a8de642017-05-11 10:59:39 -050057 std::shared_ptr<T> target;
Matthew Barthbf7b7b12017-03-07 15:46:59 -060058 namespace fs = std::experimental::filesystem;
59 static constexpr bool deferSignals = true;
60
61 auto& bus = *std::get<sdbusplus::bus::bus*>(info);
62 auto& obj = std::get<Object>(info);
63 auto& objPath = std::get<std::string>(info);
Patrick Venture9331ab72018-01-29 09:48:47 -080064 auto type = Targets<T>::type;
Matthew Barthbf7b7b12017-03-07 15:46:59 -060065
66 // Check if target sysfs file exists
Patrick Venture9331ab72018-01-29 09:48:47 -080067 std::string sysfsFullPath;
68
69 using namespace std::literals;
70 const std::string pwm = "pwm"s;
71 const std::string empty = ""s;
72
73 if (InterfaceType::FAN_PWM == type)
74 {
75 /* We're leveraging that the sensor ID matches for PWM.
76 * TODO(venture): There's a CL from intel that allows
77 * this to be specified via an environment variable.
78 */
79 sysfsFullPath = sysfs::make_sysfs_path(ioAccess.path(),
80 pwm,
81 sensor.second,
82 empty);
83 }
84 else
85 {
86 sysfsFullPath = sysfs::make_sysfs_path(ioAccess.path(),
87 sensor.first,
88 sensor.second,
89 hwmon::entry::target);
90 }
91
Matthew Barth048ac872017-03-09 14:36:08 -060092 if (fs::exists(sysfsFullPath))
Matthew Barthbf7b7b12017-03-07 15:46:59 -060093 {
Matt Spinlerb4e65572017-10-17 10:09:18 -050094 uint32_t targetSpeed = 0;
95
96 try
97 {
Patrick Venture9331ab72018-01-29 09:48:47 -080098 if (InterfaceType::FAN_PWM == type)
99 {
100 targetSpeed = ioAccess.read(
101 pwm,
102 sensor.second,
103 empty,
104 sysfs::hwmonio::retries,
105 sysfs::hwmonio::delay);
106 }
107 else
108 {
109 targetSpeed = ioAccess.read(
110 sensor.first,
111 sensor.second,
112 hwmon::entry::target,
113 sysfs::hwmonio::retries,
114 sysfs::hwmonio::delay);
115 }
Matt Spinlerb4e65572017-10-17 10:09:18 -0500116 }
117 catch (const std::system_error& e)
118 {
119 using namespace phosphor::logging;
120 using namespace sdbusplus::xyz::openbmc_project::
121 Sensor::Device::Error;
122 using metadata = xyz::openbmc_project::Sensor::
123 Device::ReadFailure;
124
125 report<ReadFailure>(
126 metadata::CALLOUT_ERRNO(e.code().value()),
127 metadata::CALLOUT_DEVICE_PATH(devPath.c_str()));
128
129 log<level::INFO>("Logging failing sysfs file",
130 phosphor::logging::entry(
131 "FILE=%s", sysfsFullPath.c_str()));
132 }
133
134 target = std::make_shared<T>(ioAccess.path(),
Brad Bishop751043e2017-08-29 11:13:46 -0400135 devPath,
Matt Spinler0a8de642017-05-11 10:59:39 -0500136 sensor.second,
137 bus,
138 objPath.c_str(),
Matt Spinlerb4e65572017-10-17 10:09:18 -0500139 deferSignals,
140 targetSpeed);
Matthew Barthbf7b7b12017-03-07 15:46:59 -0600141 auto type = Targets<T>::type;
Matt Spinler0a8de642017-05-11 10:59:39 -0500142 obj[type] = target;
Matthew Barthbf7b7b12017-03-07 15:46:59 -0600143 }
Matt Spinler0a8de642017-05-11 10:59:39 -0500144
145 return target;
Matthew Barthbf7b7b12017-03-07 15:46:59 -0600146}