#pragma once #include "config.h" #include "occ_errors.hpp" #include "occ_events.hpp" #include "occ_ffdc.hpp" #include "occ_presence.hpp" #include "powermode.hpp" #include #include #include #include namespace open_power { namespace occ { class Manager; class Status; namespace fs = std::filesystem; using namespace sdbusplus::org::open_power::OCC::Device::Error; /** @class Device * @brief Binds and unbinds the OCC driver upon request */ class Device { public: Device() = delete; ~Device() = default; Device(const Device&) = delete; Device& operator=(const Device&) = delete; Device(Device&&) = default; Device& operator=(Device&&) = default; /** @brief Constructs the Device object * * @param[in] event - Unique ptr reference to sd_event * @param[in] path - Path to the OCC instance * @param[in] manager - OCC manager instance * @param[in] status - Status instance * @param[in] instance - OCC instance number */ Device(EventPtr& event, const fs::path& path, Manager& manager, Status& status, #ifdef POWER10 std::unique_ptr& powerModeRef, #endif unsigned int instance = 0) : devPath(path), instance(instance), statusObject(status), managerObject(manager), error(event, path / "occ_error", std::bind(std::mem_fn(&Device::errorCallback), this, std::placeholders::_1)), timeout(event, path / fs::path("../../sbefifo" + std::to_string(instance + 1)) / "timeout", #ifdef PLDM std::bind(std::mem_fn(&Device::timeoutCallback), this, std::placeholders::_1) #else nullptr #endif ), ffdc(event, path / "ffdc", instance), presence(event, path / "occs_present", manager, std::bind(std::mem_fn(&Device::errorCallback), this, std::placeholders::_1)), throttleProcTemp( event, path / "occ_dvfs_overtemp", std::bind(std::mem_fn(&Device::throttleProcTempCallback), this, std::placeholders::_1)), throttleProcPower( event, path / "occ_dvfs_power", std::bind(std::mem_fn(&Device::throttleProcPowerCallback), this, std::placeholders::_1)), throttleMemTemp(event, path / "occ_mem_throttle", std::bind(std::mem_fn(&Device::throttleMemTempCallback), this, std::placeholders::_1)) #ifdef POWER10 , pmode(powerModeRef) #endif { // Nothing to do here } /** @brief Sets the device active or inactive * * @param[in] active - Indicates whether or not to set the device active */ void setActive(bool active); /** @brief Starts to monitor for errors * * @param[in] poll - Indicates whether or not the error file should * actually be polled for changes. Disabling polling is * necessary for error files that don't support the poll * file operation. */ inline void addErrorWatch(bool poll = true) { try { throttleProcTemp.addWatch(poll); } catch (const OpenFailure& e) { // try the old kernel version throttleProcTemp.setFile(devPath / "occ_dvfs_ot"); throttleProcTemp.addWatch(poll); } #ifdef POWER10 if (master()) { pmode->addIpsWatch(poll); } #endif throttleProcPower.addWatch(poll); throttleMemTemp.addWatch(poll); try { ffdc.addWatch(poll); } catch (const OpenFailure& e) { // nothing to do if there is no FFDC file } try { timeout.addWatch(poll); } catch (const std::exception& e) { // nothing to do if there is no SBE timeout file } error.addWatch(poll); } /** @brief stops monitoring for errors */ inline void removeErrorWatch() { // we can always safely remove watch even if we don't add it presence.removeWatch(); ffdc.removeWatch(); error.removeWatch(); timeout.removeWatch(); throttleMemTemp.removeWatch(); throttleProcPower.removeWatch(); throttleProcTemp.removeWatch(); #ifdef POWER10 if (master()) { pmode->removeIpsWatch(); } #endif } /** @brief Starts to watch how many OCCs are present on the master */ inline void addPresenceWatchMaster() { if (master()) { presence.addWatch(); } } /** @brief helper function to get the last part of the path * * @param[in] path - Path to parse * @return - Last directory name in the path */ static std::string getPathBack(const fs::path& path); /** @brief Returns true if the device is active */ bool active() const; /** @brief Returns true if device represents the master OCC */ bool master() const; private: /** @brief This directory contains the error files */ const fs::path devPath; /** @brief OCC instance ID */ const unsigned int instance; /** Store the associated Status instance */ Status& statusObject; /** Store the parent Manager instance */ Manager& managerObject; /** Abstraction of error monitoring */ Error error; /** Abstraction of SBE timeout monitoring */ Error timeout; /** SBE FFDC monitoring */ FFDC ffdc; /** Abstraction of OCC presence monitoring */ Presence presence; /** Error instances for watching for throttling events */ Error throttleProcTemp; Error throttleProcPower; Error throttleMemTemp; #ifdef POWER10 /** @brief OCC PowerMode object */ std::unique_ptr& pmode; #endif /** @brief file reader to read a binary string ("1" or "0") * * @param[in] fileName - Name of file to be read * @return - The value returned by reading the file */ bool readBinary(const std::string& fileName) const; /** @brief file writer to achieve bind and unbind * * @param[in] filename - Name of file to be written * @param[in] data - Data to be written to * @return - None */ void write(const fs::path& fileName, const std::string& data) { // If there is an error, move the exception all the way up std::ofstream file(fileName, std::ios::out); file << data; file.close(); return; } /** @brief callback for OCC error monitoring * * @param[in] error - Errno stored in the error file, 0 if no error */ void errorCallback(int error); /** @brief callback for OCC presence monitoring * * @param[in] occsPresent - The number of OCCs indicated in the poll * response */ void presenceCallback(int occsPresent); #ifdef PLDM /** @brief callback for SBE timeout monitoring * * @param[in] error - True if an error is reported, false otherwise */ void timeoutCallback(int error); #endif /** @brief callback for the proc temp throttle event * * @param[in] error - True if an error is reported, false otherwise */ void throttleProcTempCallback(int error); /** @brief callback for the proc power throttle event * * @param[in] error - True if an error is reported, false otherwise */ void throttleProcPowerCallback(int error); /** @brief callback for the proc temp throttle event * * @param[in] error - True if an error is reported, false otherwise */ void throttleMemTempCallback(int error); /** @brief Get the pathname for a file based on a regular expression * * @param[in] basePath - The path where the files will be checked * @param[in] expr - Regular expression describing the target file * * @return path to the file or empty path if not found */ fs::path getFilenameByRegex(fs::path basePath, const std::regex& expr) const; }; } // namespace occ } // namespace open_power