blob: 3c6dc0d9086a3285a371d25e8b525ded69a40dd8 [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
Matt Spinlera7e2c1e2018-02-23 12:18:19 -060010enum class targetType
11{
12 DEFAULT,
13 RPM,
14 PWM
15};
16
17static constexpr auto RPM_TARGET = "RPM";
18static constexpr auto PWM_TARGET = "PWM";
19
Matthew Barthbf7b7b12017-03-07 15:46:59 -060020/** @class Targets
21 * @brief Target type traits.
22 *
23 * @tparam T - The target type.
24 */
25template <typename T>
26struct Targets
27{
28 static void fail()
29 {
30 static_assert(sizeof(Targets) == -1, "Unsupported Target type");
31 }
32};
33
34/**@brief Targets specialization for fan speed. */
35template <>
Matthew Barth048ac872017-03-09 14:36:08 -060036struct Targets<hwmon::FanSpeed>
Matthew Barthbf7b7b12017-03-07 15:46:59 -060037{
38 static constexpr InterfaceType type = InterfaceType::FAN_SPEED;
Matthew Barthbf7b7b12017-03-07 15:46:59 -060039};
40
Patrick Venture9331ab72018-01-29 09:48:47 -080041template <>
42struct Targets<hwmon::FanPwm>
43{
44 static constexpr InterfaceType type = InterfaceType::FAN_PWM;
45};
46
Matthew Barthbf7b7b12017-03-07 15:46:59 -060047/** @brief addTarget
48 *
49 * Creates the target type interface
50 *
51 * @tparam T - The target type
52 *
53 * @param[in] sensor - A sensor type and name
Matt Spinlerb4e65572017-10-17 10:09:18 -050054 * @param[in] ioAccess - hwmon sysfs access object
55 * @param[in] devPath - The /sys/devices sysfs path
Matthew Barthbf7b7b12017-03-07 15:46:59 -060056 * @param[in] info - The sdbusplus server connection and interfaces
Matt Spinler0a8de642017-05-11 10:59:39 -050057 *
58 * @return A shared pointer to the target interface object
59 * Will be empty if no interface was created
Matthew Barthbf7b7b12017-03-07 15:46:59 -060060 */
61template <typename T>
Matt Spinler0a8de642017-05-11 10:59:39 -050062std::shared_ptr<T> addTarget(const SensorSet::key_type& sensor,
Matt Spinlerb4e65572017-10-17 10:09:18 -050063 const sysfs::hwmonio::HwmonIO& ioAccess,
Brad Bishop751043e2017-08-29 11:13:46 -040064 const std::string& devPath,
Matt Spinler0a8de642017-05-11 10:59:39 -050065 ObjectInfo& info)
Matthew Barthbf7b7b12017-03-07 15:46:59 -060066{
Matt Spinler0a8de642017-05-11 10:59:39 -050067 std::shared_ptr<T> target;
Matthew Barthbf7b7b12017-03-07 15:46:59 -060068 namespace fs = std::experimental::filesystem;
69 static constexpr bool deferSignals = true;
70
71 auto& bus = *std::get<sdbusplus::bus::bus*>(info);
72 auto& obj = std::get<Object>(info);
73 auto& objPath = std::get<std::string>(info);
Patrick Venture9331ab72018-01-29 09:48:47 -080074 auto type = Targets<T>::type;
Matthew Barthbf7b7b12017-03-07 15:46:59 -060075
76 // Check if target sysfs file exists
Patrick Venture9331ab72018-01-29 09:48:47 -080077 std::string sysfsFullPath;
Lei YUa4bba962018-01-31 13:51:05 +080078 std::string targetName = sensor.first;
79 std::string targetId = sensor.second;
80 std::string entry = hwmon::entry::target;
Patrick Venture9331ab72018-01-29 09:48:47 -080081
82 using namespace std::literals;
83 const std::string pwm = "pwm"s;
84 const std::string empty = ""s;
85
86 if (InterfaceType::FAN_PWM == type)
87 {
Lei YUa4bba962018-01-31 13:51:05 +080088 targetName = pwm;
89 // If PWM_TARGET is set, use the specified pwm id
90 auto id = getEnv("PWM_TARGET", sensor);
91 if (!id.empty())
92 {
93 targetId = id;
94 }
95 entry = empty;
Patrick Venture9331ab72018-01-29 09:48:47 -080096 }
97
Lei YUa4bba962018-01-31 13:51:05 +080098 sysfsFullPath = sysfs::make_sysfs_path(ioAccess.path(),
99 targetName,
100 targetId,
101 entry);
Matthew Barth048ac872017-03-09 14:36:08 -0600102 if (fs::exists(sysfsFullPath))
Matthew Barthbf7b7b12017-03-07 15:46:59 -0600103 {
Matthew Barth28f8e662018-03-26 16:57:36 -0500104 auto useTarget = true;
105 auto tmEnv = getenv("TARGET_MODE");
106 if (tmEnv)
Matt Spinlerb4e65572017-10-17 10:09:18 -0500107 {
Matthew Barth28f8e662018-03-26 16:57:36 -0500108 std::string mode{tmEnv};
109 std::transform(mode.begin(), mode.end(), mode.begin(), toupper);
Matt Spinlerb4e65572017-10-17 10:09:18 -0500110
Matthew Barth28f8e662018-03-26 16:57:36 -0500111 if (mode == RPM_TARGET)
112 {
113 if (type != InterfaceType::FAN_SPEED)
114 {
115 useTarget = false;
116 }
117 }
118 else if (mode == PWM_TARGET)
119 {
120 if (type != InterfaceType::FAN_PWM)
121 {
122 useTarget = false;
123 }
124 }
125 else
126 {
127 using namespace phosphor::logging;
128 log<level::ERR>("Invalid TARGET_MODE env var found",
129 phosphor::logging::entry(
130 "TARGET_MODE=%s", tmEnv),
131 phosphor::logging::entry(
132 "DEVPATH=%s", devPath.c_str()));
133 }
Matt Spinlerb4e65572017-10-17 10:09:18 -0500134 }
135
Matthew Barth28f8e662018-03-26 16:57:36 -0500136 if (useTarget)
137 {
138 uint32_t targetSpeed = 0;
139
140 try
141 {
142 targetSpeed = ioAccess.read(
143 targetName,
144 targetId,
145 entry,
146 sysfs::hwmonio::retries,
147 sysfs::hwmonio::delay);
148 }
149 catch (const std::system_error& e)
150 {
151 using namespace phosphor::logging;
152 using namespace sdbusplus::xyz::openbmc_project::
153 Sensor::Device::Error;
154 using metadata = xyz::openbmc_project::Sensor::
155 Device::ReadFailure;
156
157 report<ReadFailure>(
158 metadata::CALLOUT_ERRNO(e.code().value()),
159 metadata::CALLOUT_DEVICE_PATH(devPath.c_str()));
160
161 log<level::INFO>("Logging failing sysfs file",
162 phosphor::logging::entry(
163 "FILE=%s", sysfsFullPath.c_str()));
164 }
165
166 target = std::make_shared<T>(ioAccess.path(),
167 devPath,
168 targetId,
169 bus,
170 objPath.c_str(),
171 deferSignals,
172 targetSpeed);
173 obj[type] = target;
174 }
Matthew Barthbf7b7b12017-03-07 15:46:59 -0600175 }
Matt Spinler0a8de642017-05-11 10:59:39 -0500176
177 return target;
Matthew Barthbf7b7b12017-03-07 15:46:59 -0600178}