blob: fe256a33513c11e72c7a539b98ad94c138c5ccc3 [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>
Patrick Venture7a5285d2018-04-17 19:15:05 -07007#include "env.hpp"
Matthew Barth048ac872017-03-09 14:36:08 -06008#include "fan_speed.hpp"
Patrick Venture9331ab72018-01-29 09:48:47 -08009#include "fan_pwm.hpp"
Matthew Barthbf7b7b12017-03-07 15:46:59 -060010
Matt Spinlera7e2c1e2018-02-23 12:18:19 -060011enum class targetType
12{
13 DEFAULT,
14 RPM,
15 PWM
16};
17
18static constexpr auto RPM_TARGET = "RPM";
19static constexpr auto PWM_TARGET = "PWM";
20
Matthew Barthbf7b7b12017-03-07 15:46:59 -060021/** @class Targets
22 * @brief Target type traits.
23 *
24 * @tparam T - The target type.
25 */
26template <typename T>
27struct Targets
28{
29 static void fail()
30 {
31 static_assert(sizeof(Targets) == -1, "Unsupported Target type");
32 }
33};
34
35/**@brief Targets specialization for fan speed. */
36template <>
Matthew Barth048ac872017-03-09 14:36:08 -060037struct Targets<hwmon::FanSpeed>
Matthew Barthbf7b7b12017-03-07 15:46:59 -060038{
39 static constexpr InterfaceType type = InterfaceType::FAN_SPEED;
Matthew Barthbf7b7b12017-03-07 15:46:59 -060040};
41
Patrick Venture9331ab72018-01-29 09:48:47 -080042template <>
43struct Targets<hwmon::FanPwm>
44{
45 static constexpr InterfaceType type = InterfaceType::FAN_PWM;
46};
47
Matthew Barthbf7b7b12017-03-07 15:46:59 -060048/** @brief addTarget
49 *
50 * Creates the target type interface
51 *
52 * @tparam T - The target type
53 *
54 * @param[in] sensor - A sensor type and name
Matt Spinlerb4e65572017-10-17 10:09:18 -050055 * @param[in] ioAccess - hwmon sysfs access object
56 * @param[in] devPath - The /sys/devices sysfs path
Matthew Barthbf7b7b12017-03-07 15:46:59 -060057 * @param[in] info - The sdbusplus server connection and interfaces
Matt Spinler0a8de642017-05-11 10:59:39 -050058 *
59 * @return A shared pointer to the target interface object
60 * Will be empty if no interface was created
Matthew Barthbf7b7b12017-03-07 15:46:59 -060061 */
62template <typename T>
Matt Spinler0a8de642017-05-11 10:59:39 -050063std::shared_ptr<T> addTarget(const SensorSet::key_type& sensor,
Matt Spinlerb4e65572017-10-17 10:09:18 -050064 const sysfs::hwmonio::HwmonIO& ioAccess,
Brad Bishop751043e2017-08-29 11:13:46 -040065 const std::string& devPath,
Matt Spinler0a8de642017-05-11 10:59:39 -050066 ObjectInfo& info)
Matthew Barthbf7b7b12017-03-07 15:46:59 -060067{
Matt Spinler0a8de642017-05-11 10:59:39 -050068 std::shared_ptr<T> target;
Matthew Barthbf7b7b12017-03-07 15:46:59 -060069 namespace fs = std::experimental::filesystem;
70 static constexpr bool deferSignals = true;
71
72 auto& bus = *std::get<sdbusplus::bus::bus*>(info);
73 auto& obj = std::get<Object>(info);
74 auto& objPath = std::get<std::string>(info);
Patrick Venture9331ab72018-01-29 09:48:47 -080075 auto type = Targets<T>::type;
Matthew Barthbf7b7b12017-03-07 15:46:59 -060076
77 // Check if target sysfs file exists
Patrick Venture9331ab72018-01-29 09:48:47 -080078 std::string sysfsFullPath;
Lei YUa4bba962018-01-31 13:51:05 +080079 std::string targetName = sensor.first;
80 std::string targetId = sensor.second;
81 std::string entry = hwmon::entry::target;
Patrick Venture9331ab72018-01-29 09:48:47 -080082
83 using namespace std::literals;
84 const std::string pwm = "pwm"s;
85 const std::string empty = ""s;
86
87 if (InterfaceType::FAN_PWM == type)
88 {
Lei YUa4bba962018-01-31 13:51:05 +080089 targetName = pwm;
90 // If PWM_TARGET is set, use the specified pwm id
Patrick Venture7a5285d2018-04-17 19:15:05 -070091 auto id = env::getEnv("PWM_TARGET", sensor);
Lei YUa4bba962018-01-31 13:51:05 +080092 if (!id.empty())
93 {
94 targetId = id;
95 }
96 entry = empty;
Patrick Venture9331ab72018-01-29 09:48:47 -080097 }
98
Lei YUa4bba962018-01-31 13:51:05 +080099 sysfsFullPath = sysfs::make_sysfs_path(ioAccess.path(),
100 targetName,
101 targetId,
102 entry);
Matthew Barth048ac872017-03-09 14:36:08 -0600103 if (fs::exists(sysfsFullPath))
Matthew Barthbf7b7b12017-03-07 15:46:59 -0600104 {
Matthew Barth28f8e662018-03-26 16:57:36 -0500105 auto useTarget = true;
106 auto tmEnv = getenv("TARGET_MODE");
107 if (tmEnv)
Matt Spinlerb4e65572017-10-17 10:09:18 -0500108 {
Matthew Barth28f8e662018-03-26 16:57:36 -0500109 std::string mode{tmEnv};
110 std::transform(mode.begin(), mode.end(), mode.begin(), toupper);
Matt Spinlerb4e65572017-10-17 10:09:18 -0500111
Matthew Barth28f8e662018-03-26 16:57:36 -0500112 if (mode == RPM_TARGET)
113 {
114 if (type != InterfaceType::FAN_SPEED)
115 {
116 useTarget = false;
117 }
118 }
119 else if (mode == PWM_TARGET)
120 {
121 if (type != InterfaceType::FAN_PWM)
122 {
123 useTarget = false;
124 }
125 }
126 else
127 {
128 using namespace phosphor::logging;
129 log<level::ERR>("Invalid TARGET_MODE env var found",
130 phosphor::logging::entry(
131 "TARGET_MODE=%s", tmEnv),
132 phosphor::logging::entry(
133 "DEVPATH=%s", devPath.c_str()));
134 }
Matt Spinlerb4e65572017-10-17 10:09:18 -0500135 }
136
Matthew Barth28f8e662018-03-26 16:57:36 -0500137 if (useTarget)
138 {
139 uint32_t targetSpeed = 0;
140
141 try
142 {
143 targetSpeed = ioAccess.read(
144 targetName,
145 targetId,
146 entry,
147 sysfs::hwmonio::retries,
148 sysfs::hwmonio::delay);
149 }
150 catch (const std::system_error& e)
151 {
152 using namespace phosphor::logging;
153 using namespace sdbusplus::xyz::openbmc_project::
154 Sensor::Device::Error;
155 using metadata = xyz::openbmc_project::Sensor::
156 Device::ReadFailure;
157
158 report<ReadFailure>(
159 metadata::CALLOUT_ERRNO(e.code().value()),
160 metadata::CALLOUT_DEVICE_PATH(devPath.c_str()));
161
162 log<level::INFO>("Logging failing sysfs file",
163 phosphor::logging::entry(
164 "FILE=%s", sysfsFullPath.c_str()));
165 }
166
167 target = std::make_shared<T>(ioAccess.path(),
168 devPath,
169 targetId,
170 bus,
171 objPath.c_str(),
172 deferSignals,
173 targetSpeed);
174 obj[type] = target;
175 }
Matthew Barthbf7b7b12017-03-07 15:46:59 -0600176 }
Matt Spinler0a8de642017-05-11 10:59:39 -0500177
178 return target;
Matthew Barthbf7b7b12017-03-07 15:46:59 -0600179}