diff options
author | Brandon Wyman <v2cib530@us.ibm.com> | 2017-05-31 18:26:30 -0500 |
---|---|---|
committer | Brandon Wyman <v2cib530@us.ibm.com> | 2017-06-06 11:37:02 -0500 |
commit | 8af8a2002f54178c64d59c86a8abe57bd3787b56 (patch) | |
tree | 0fef6f81b32503b0cab20e919d55cc6643fc9f0d /sysfs.cpp | |
parent | 4eb9858d2025128ffb45c6f965d49cef58559c6a (diff) | |
download | phosphor-hwmon-8af8a2002f54178c64d59c86a8abe57bd3787b56.tar.gz phosphor-hwmon-8af8a2002f54178c64d59c86a8abe57bd3787b56.zip |
Update call out algorithm for iio hwmon instance
When readSysfsWithCallout() or writeSysfsWithCallout() get run, use the
instancePath to search for a call out path. For instances with an hwmon
driver, the passed in path should be used. For instances with an iio
driver, search for a phandle file that has a value matching to that in
the io-channels file for this phosphor-hwmon instance. If an error occurs
on the read or write, use that matching phandle path to create a call
out path.
Resolves openbmc/openbmc#1265
Change-Id: I6390d0dfb3d67ce8a55d171ca9a3cb8f3057a8c9
Signed-off-by: Brandon Wyman <v2cib530@us.ibm.com>
Diffstat (limited to 'sysfs.cpp')
-rw-r--r-- | sysfs.cpp | 114 |
1 files changed, 91 insertions, 23 deletions
@@ -25,30 +25,37 @@ #include <fstream> using namespace phosphor::logging; +namespace fs = std::experimental::filesystem; -std::string findHwmon(const std::string& ofNode) -{ - namespace fs = std::experimental::filesystem; - static constexpr auto hwmonRoot = "/sys/class/hwmon"; - static constexpr auto ofRoot = "/sys/firmware/devicetree/base"; +static constexpr auto ofRoot = "/sys/firmware/devicetree/base"; - fs::path fullOfPath{ofRoot}; - fullOfPath /= ofNode; - fs::path fullOfPathPhandle{fullOfPath}; - fullOfPathPhandle /= "phandle"; - - for (const auto& hwmonInst : fs::directory_iterator(hwmonRoot)) +/** + * @brief Return the path to the phandle file matching value in io-channels. + * + * This function will take two passed in paths. + * One path is used to find the io-channels file. + * The other path is used to find the phandle file. + * The 4 byte phandle value is read from the phandle file(s). + * The 4 byte phandle value and 4 byte index value is read from io-channels. + * When a match is found, the path to the matching phandle file is returned. + * + * @param[in] iochanneldir - Path to file for getting phandle from io-channels + * @param[in] phandledir - Path to use for reading from phandle file + * + * @return Path to phandle file with value matching that in io-channels + */ +std::string findPhandleMatch(const std::string& iochanneldir, + const std::string& phandledir) +{ + for (const auto& ofInst : fs::recursive_directory_iterator(phandledir)) { - auto path = hwmonInst.path(); - path /= "of_node"; - - if (fs::canonical(path) != fullOfPath) + auto path = ofInst.path(); + if ("phandle" == ofInst.path().filename()) { - // Try to find HWMON instance via phandle values. - // Used for IIO device drivers. - path /= "io-channels"; - if (fs::exists(path) && fs::exists(fullOfPathPhandle)) + auto ioChannelsPath = iochanneldir + "/io-channels"; + if (fs::exists(ioChannelsPath)) { + auto fullOfPathPhandle = ofInst.path(); std::ifstream ioChannelsFile(path); std::ifstream pHandleFile(fullOfPathPhandle); @@ -64,17 +71,74 @@ std::string findHwmon(const std::string& ofNode) if (ioChannelsValue == pHandleValue) { - return hwmonInst.path(); + return ofInst.path(); } } catch (const std::exception& e) { log<level::INFO>(e.what()); + continue; } + } + } + } + + return std::string(); +} + +/** + * @brief Return the path to use for a call out. + * + * If the path does not contain iio-hwmon, assume passed in path is the call + * out path. + * + * @param[in] ofPath - Open firmware path to search for matching phandle value + * + * @return Path to use for call out + */ +std::string findCalloutPath(const std::string& ofPath) +{ + static constexpr auto iioHwmonStr = "iio-hwmon"; + + if (ofPath.find(iioHwmonStr) != std::string::npos) + { + auto matchpath = findPhandleMatch(ofPath, ofRoot); + auto n = matchpath.rfind('/'); + if (n != std::string::npos) + { + return matchpath.substr(0, n); + } + } + + return ofPath; +} + +std::string findHwmon(const std::string& ofNode) +{ + static constexpr auto hwmonRoot = "/sys/class/hwmon"; + + fs::path fullOfPath{ofRoot}; + fullOfPath /= ofNode; + for (const auto& hwmonInst : fs::directory_iterator(hwmonRoot)) + { + auto path = hwmonInst.path(); + path /= "of_node"; + if (fs::canonical(path) != fullOfPath) + { + // Try to find HWMON instance via phandle values. + // Used for IIO device drivers. + auto ofpath = fullOfPath.string(); + auto matchpath = findPhandleMatch(path, ofpath); + if (!std::string(matchpath).empty()) + { + return hwmonInst.path(); + } + else + { + continue; } - continue; } return hwmonInst.path(); @@ -98,6 +162,8 @@ int readSysfsWithCallout(const std::string& root, std::string fullPath = make_sysfs_path(instancePath, type, id, sensor); + auto callOutPath = findCalloutPath(fs::canonical(instancePath)); + ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit); @@ -121,7 +187,7 @@ int readSysfsWithCallout(const std::string& root, ReadFailure::CALLOUT_ERRNO(rc), xyz::openbmc_project::Sensor::Device:: ReadFailure::CALLOUT_DEVICE_PATH( - fs::canonical(instancePath).c_str())); + fs::canonical(callOutPath).c_str())); exit(EXIT_FAILURE); } @@ -145,6 +211,8 @@ uint64_t writeSysfsWithCallout(const uint64_t& value, std::string fullPath = make_sysfs_path(instancePath, type, id, sensor); + auto callOutPath = findCalloutPath(fs::canonical(instancePath)); + ofs.exceptions(std::ofstream::failbit | std::ofstream::badbit | std::ofstream::eofbit); @@ -165,7 +233,7 @@ uint64_t writeSysfsWithCallout(const uint64_t& value, WriteFailure::CALLOUT_ERRNO(rc), xyz::openbmc_project::Control::Device:: WriteFailure::CALLOUT_DEVICE_PATH( - fs::canonical(instancePath).c_str())); + fs::canonical(callOutPath).c_str())); exit(EXIT_FAILURE); } |