| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 1 | #pragma once | 
|  | 2 |  | 
| Patrick Venture | 043d323 | 2018-08-31 10:10:53 -0700 | [diff] [blame] | 3 | #include "env.hpp" | 
|  | 4 | #include "fan_pwm.hpp" | 
|  | 5 | #include "fan_speed.hpp" | 
|  | 6 | #include "hwmonio.hpp" | 
|  | 7 |  | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 8 | #include <experimental/filesystem> | 
| Patrick Venture | 5055237 | 2018-06-07 10:53:56 -0700 | [diff] [blame] | 9 | #include <memory> | 
| Matt Spinler | b4e6557 | 2017-10-17 10:09:18 -0500 | [diff] [blame] | 10 | #include <phosphor-logging/elog-errors.hpp> | 
|  | 11 | #include <phosphor-logging/log.hpp> | 
|  | 12 | #include <xyz/openbmc_project/Sensor/Device/error.hpp> | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 13 |  | 
| Matt Spinler | a7e2c1e | 2018-02-23 12:18:19 -0600 | [diff] [blame] | 14 | enum class targetType | 
|  | 15 | { | 
|  | 16 | DEFAULT, | 
|  | 17 | RPM, | 
|  | 18 | PWM | 
|  | 19 | }; | 
|  | 20 |  | 
|  | 21 | static constexpr auto RPM_TARGET = "RPM"; | 
|  | 22 | static constexpr auto PWM_TARGET = "PWM"; | 
|  | 23 |  | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 24 | /** @class Targets | 
|  | 25 | *  @brief Target type traits. | 
|  | 26 | * | 
|  | 27 | *  @tparam T - The target type. | 
|  | 28 | */ | 
|  | 29 | template <typename T> | 
|  | 30 | struct Targets | 
|  | 31 | { | 
|  | 32 | static void fail() | 
|  | 33 | { | 
|  | 34 | static_assert(sizeof(Targets) == -1, "Unsupported Target type"); | 
|  | 35 | } | 
|  | 36 | }; | 
|  | 37 |  | 
|  | 38 | /**@brief Targets specialization for fan speed. */ | 
|  | 39 | template <> | 
| Matthew Barth | 048ac87 | 2017-03-09 14:36:08 -0600 | [diff] [blame] | 40 | struct Targets<hwmon::FanSpeed> | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 41 | { | 
|  | 42 | static constexpr InterfaceType type = InterfaceType::FAN_SPEED; | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 43 | }; | 
|  | 44 |  | 
| Patrick Venture | 9331ab7 | 2018-01-29 09:48:47 -0800 | [diff] [blame] | 45 | template <> | 
|  | 46 | struct Targets<hwmon::FanPwm> | 
|  | 47 | { | 
|  | 48 | static constexpr InterfaceType type = InterfaceType::FAN_PWM; | 
|  | 49 | }; | 
|  | 50 |  | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 51 | /** @brief addTarget | 
|  | 52 | * | 
|  | 53 | *  Creates the target type interface | 
|  | 54 | * | 
|  | 55 | *  @tparam T - The target type | 
|  | 56 | * | 
|  | 57 | *  @param[in] sensor - A sensor type and name | 
| Matt Spinler | b4e6557 | 2017-10-17 10:09:18 -0500 | [diff] [blame] | 58 | *  @param[in] ioAccess - hwmon sysfs access object | 
|  | 59 | *  @param[in] devPath - The /sys/devices sysfs path | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 60 | *  @param[in] info - The sdbusplus server connection and interfaces | 
| Matt Spinler | 0a8de64 | 2017-05-11 10:59:39 -0500 | [diff] [blame] | 61 | * | 
|  | 62 | *  @return A shared pointer to the target interface object | 
|  | 63 | *          Will be empty if no interface was created | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 64 | */ | 
|  | 65 | template <typename T> | 
| Matt Spinler | 0a8de64 | 2017-05-11 10:59:39 -0500 | [diff] [blame] | 66 | std::shared_ptr<T> addTarget(const SensorSet::key_type& sensor, | 
| Patrick Venture | 75e56c6 | 2018-04-20 18:10:15 -0700 | [diff] [blame] | 67 | const hwmonio::HwmonIO& ioAccess, | 
| Patrick Venture | 043d323 | 2018-08-31 10:10:53 -0700 | [diff] [blame] | 68 | const std::string& devPath, ObjectInfo& info) | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 69 | { | 
| Matt Spinler | 0a8de64 | 2017-05-11 10:59:39 -0500 | [diff] [blame] | 70 | std::shared_ptr<T> target; | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 71 | namespace fs = std::experimental::filesystem; | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 72 |  | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 73 | auto& obj = std::get<Object>(info); | 
|  | 74 | auto& objPath = std::get<std::string>(info); | 
| Patrick Venture | 9331ab7 | 2018-01-29 09:48:47 -0800 | [diff] [blame] | 75 | auto type = Targets<T>::type; | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 76 |  | 
|  | 77 | // Check if target sysfs file exists | 
| Patrick Venture | 9331ab7 | 2018-01-29 09:48:47 -0800 | [diff] [blame] | 78 | std::string sysfsFullPath; | 
| Lei YU | a4bba96 | 2018-01-31 13:51:05 +0800 | [diff] [blame] | 79 | std::string targetName = sensor.first; | 
|  | 80 | std::string targetId = sensor.second; | 
|  | 81 | std::string entry = hwmon::entry::target; | 
| Patrick Venture | 9331ab7 | 2018-01-29 09:48:47 -0800 | [diff] [blame] | 82 |  | 
|  | 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 YU | a4bba96 | 2018-01-31 13:51:05 +0800 | [diff] [blame] | 89 | targetName = pwm; | 
|  | 90 | // If PWM_TARGET is set, use the specified pwm id | 
| Patrick Venture | 7a5285d | 2018-04-17 19:15:05 -0700 | [diff] [blame] | 91 | auto id = env::getEnv("PWM_TARGET", sensor); | 
| Lei YU | a4bba96 | 2018-01-31 13:51:05 +0800 | [diff] [blame] | 92 | if (!id.empty()) | 
|  | 93 | { | 
|  | 94 | targetId = id; | 
|  | 95 | } | 
|  | 96 | entry = empty; | 
| Patrick Venture | 9331ab7 | 2018-01-29 09:48:47 -0800 | [diff] [blame] | 97 | } | 
|  | 98 |  | 
| Patrick Venture | 043d323 | 2018-08-31 10:10:53 -0700 | [diff] [blame] | 99 | sysfsFullPath = | 
|  | 100 | sysfs::make_sysfs_path(ioAccess.path(), targetName, targetId, entry); | 
| Matthew Barth | 048ac87 | 2017-03-09 14:36:08 -0600 | [diff] [blame] | 101 | if (fs::exists(sysfsFullPath)) | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 102 | { | 
| Matthew Barth | 28f8e66 | 2018-03-26 16:57:36 -0500 | [diff] [blame] | 103 | auto useTarget = true; | 
| Patrick Venture | a24c880 | 2018-04-17 19:38:06 -0700 | [diff] [blame] | 104 | auto tmEnv = env::getEnv("TARGET_MODE"); | 
|  | 105 | if (!tmEnv.empty()) | 
| Matt Spinler | b4e6557 | 2017-10-17 10:09:18 -0500 | [diff] [blame] | 106 | { | 
| Matthew Barth | 28f8e66 | 2018-03-26 16:57:36 -0500 | [diff] [blame] | 107 | std::string mode{tmEnv}; | 
|  | 108 | std::transform(mode.begin(), mode.end(), mode.begin(), toupper); | 
| Matt Spinler | b4e6557 | 2017-10-17 10:09:18 -0500 | [diff] [blame] | 109 |  | 
| Matthew Barth | 28f8e66 | 2018-03-26 16:57:36 -0500 | [diff] [blame] | 110 | if (mode == RPM_TARGET) | 
|  | 111 | { | 
|  | 112 | if (type != InterfaceType::FAN_SPEED) | 
|  | 113 | { | 
|  | 114 | useTarget = false; | 
|  | 115 | } | 
|  | 116 | } | 
|  | 117 | else if (mode == PWM_TARGET) | 
|  | 118 | { | 
|  | 119 | if (type != InterfaceType::FAN_PWM) | 
|  | 120 | { | 
|  | 121 | useTarget = false; | 
|  | 122 | } | 
|  | 123 | } | 
|  | 124 | else | 
|  | 125 | { | 
|  | 126 | using namespace phosphor::logging; | 
| Patrick Venture | 043d323 | 2018-08-31 10:10:53 -0700 | [diff] [blame] | 127 | log<level::ERR>( | 
|  | 128 | "Invalid TARGET_MODE env var found", | 
|  | 129 | phosphor::logging::entry("TARGET_MODE=%s", tmEnv.c_str()), | 
|  | 130 | phosphor::logging::entry("DEVPATH=%s", devPath.c_str())); | 
| Matthew Barth | 28f8e66 | 2018-03-26 16:57:36 -0500 | [diff] [blame] | 131 | } | 
| Matt Spinler | b4e6557 | 2017-10-17 10:09:18 -0500 | [diff] [blame] | 132 | } | 
|  | 133 |  | 
| Matthew Barth | 28f8e66 | 2018-03-26 16:57:36 -0500 | [diff] [blame] | 134 | if (useTarget) | 
|  | 135 | { | 
|  | 136 | uint32_t targetSpeed = 0; | 
|  | 137 |  | 
|  | 138 | try | 
|  | 139 | { | 
| Patrick Venture | 043d323 | 2018-08-31 10:10:53 -0700 | [diff] [blame] | 140 | targetSpeed = ioAccess.read(targetName, targetId, entry, | 
|  | 141 | hwmonio::retries, hwmonio::delay); | 
| Matthew Barth | 28f8e66 | 2018-03-26 16:57:36 -0500 | [diff] [blame] | 142 | } | 
|  | 143 | catch (const std::system_error& e) | 
|  | 144 | { | 
|  | 145 | using namespace phosphor::logging; | 
| Patrick Venture | 043d323 | 2018-08-31 10:10:53 -0700 | [diff] [blame] | 146 | using namespace sdbusplus::xyz::openbmc_project::Sensor:: | 
|  | 147 | Device::Error; | 
|  | 148 | using metadata = | 
|  | 149 | xyz::openbmc_project::Sensor::Device::ReadFailure; | 
| Matthew Barth | 28f8e66 | 2018-03-26 16:57:36 -0500 | [diff] [blame] | 150 |  | 
|  | 151 | report<ReadFailure>( | 
| Patrick Venture | 043d323 | 2018-08-31 10:10:53 -0700 | [diff] [blame] | 152 | metadata::CALLOUT_ERRNO(e.code().value()), | 
|  | 153 | metadata::CALLOUT_DEVICE_PATH(devPath.c_str())); | 
| Matthew Barth | 28f8e66 | 2018-03-26 16:57:36 -0500 | [diff] [blame] | 154 |  | 
| Patrick Venture | 043d323 | 2018-08-31 10:10:53 -0700 | [diff] [blame] | 155 | log<level::INFO>( | 
|  | 156 | "Logging failing sysfs file", | 
|  | 157 | phosphor::logging::entry("FILE=%s", sysfsFullPath.c_str())); | 
| Matthew Barth | 28f8e66 | 2018-03-26 16:57:36 -0500 | [diff] [blame] | 158 | } | 
|  | 159 |  | 
| Patrick Venture | 685efa1 | 2018-10-12 18:00:13 -0700 | [diff] [blame] | 160 | static constexpr bool deferSignals = true; | 
|  | 161 | auto& bus = *std::get<sdbusplus::bus::bus*>(info); | 
|  | 162 |  | 
| Patrick Venture | 5055237 | 2018-06-07 10:53:56 -0700 | [diff] [blame] | 163 | // ioAccess.path() is a path like: /sys/class/hwmon/hwmon1 | 
|  | 164 | target = std::make_shared<T>( | 
| Patrick Venture | 043d323 | 2018-08-31 10:10:53 -0700 | [diff] [blame] | 165 | std::move(std::make_unique<hwmonio::HwmonIO>(ioAccess.path())), | 
|  | 166 | devPath, targetId, bus, objPath.c_str(), deferSignals, | 
|  | 167 | targetSpeed); | 
| Matthew Barth | 28f8e66 | 2018-03-26 16:57:36 -0500 | [diff] [blame] | 168 | obj[type] = target; | 
|  | 169 | } | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 170 | } | 
| Matt Spinler | 0a8de64 | 2017-05-11 10:59:39 -0500 | [diff] [blame] | 171 |  | 
|  | 172 | return target; | 
| Matthew Barth | bf7b7b1 | 2017-03-07 15:46:59 -0600 | [diff] [blame] | 173 | } |