1 #pragma once 2 3 #include "i2c_occ.hpp" 4 #include "occ_device.hpp" 5 #include "occ_events.hpp" 6 7 #include <functional> 8 #include <org/open_power/Control/Host/server.hpp> 9 #include <org/open_power/OCC/Status/server.hpp> 10 #include <sdbusplus/bus.hpp> 11 #include <sdbusplus/server/object.hpp> 12 13 namespace open_power 14 { 15 namespace occ 16 { 17 18 class Manager; 19 namespace Base = sdbusplus::org::open_power::OCC::server; 20 using Interface = sdbusplus::server::object::object<Base::Status>; 21 22 // IPMID's host control application 23 namespace Control = sdbusplus::org::open_power::Control::server; 24 25 // For waiting on signals 26 namespace sdbusRule = sdbusplus::bus::match::rules; 27 28 // OCC status instance. Ex. for "occ0", the instance is 0 29 using instanceID = int; 30 31 // IPMI sensor ID for a given OCC instance 32 using sensorID = uint8_t; 33 34 // Human readable sensor name for DBus tree. E.g. "CPU0_OCC" 35 using sensorName = std::string; 36 37 // OCC sensors definitions in the map 38 using sensorDefs = std::tuple<sensorID, sensorName>; 39 40 // OCC sysfs name prefix 41 const std::string sysfsName = "occ-hwmon"; 42 43 /** @class Status 44 * @brief Implementation of OCC Active Status 45 */ 46 class Status : public Interface 47 { 48 public: 49 Status() = delete; 50 ~Status() = default; 51 Status(const Status&) = delete; 52 Status& operator=(const Status&) = delete; 53 Status(Status&&) = default; 54 Status& operator=(Status&&) = default; 55 56 /** @brief Constructs the Status object and 57 * the underlying device object 58 * 59 * @param[in] bus - DBus bus to attach to 60 * @param[in] event - sd_event unique pointer reference 61 * @param[in] path - DBus object path 62 * @param[in] manager - OCC manager instance 63 * @param[in] callBack - Callback handler to invoke during 64 * property change 65 */ 66 Status(sdbusplus::bus::bus& bus, EventPtr& event, const char* path, 67 const Manager& manager, 68 std::function<void(bool)> callBack = nullptr) : 69 Interface(bus, getDbusPath(path).c_str(), true), 70 bus(bus), path(path), callBack(callBack), instance(getInstance(path)), 71 device(event, 72 #ifdef I2C_OCC 73 fs::path(DEV_PATH) / i2c_occ::getI2cDeviceName(path), 74 #else 75 fs::path(DEV_PATH) / 76 fs::path(sysfsName + "." + std::to_string(instance + 1)), 77 #endif 78 manager, *this, 79 std::bind(std::mem_fn(&Status::deviceErrorHandler), this, 80 std::placeholders::_1)), 81 hostControlSignal( 82 bus, 83 sdbusRule::type::signal() + sdbusRule::member("CommandComplete") + 84 sdbusRule::path("/org/open_power/control/host0") + 85 sdbusRule::interface("org.open_power.Control.Host") + 86 sdbusRule::argN(0, Control::convertForMessage( 87 Control::Host::Command::OCCReset)), 88 std::bind(std::mem_fn(&Status::hostControlEvent), this, 89 std::placeholders::_1)) 90 { 91 // Check to see if we have OCC already bound. If so, just set it 92 if (device.bound()) 93 { 94 this->occActive(true); 95 } 96 97 // Announce that we are ready 98 this->emit_object_added(); 99 } 100 101 /** @brief Since we are overriding the setter-occActive but not the 102 * getter-occActive, we need to have this using in order to 103 * allow passthrough usage of the getter-occActive 104 */ 105 using Base::Status::occActive; 106 107 /** @brief SET OccActive to True or False 108 * 109 * @param[in] value - Intended value 110 * 111 * @return - Updated value of the property 112 */ 113 bool occActive(bool value) override; 114 115 /** @brief Starts OCC error detection */ 116 inline void addErrorWatch() 117 { 118 return device.addErrorWatch(); 119 } 120 121 /** @brief Stops OCC error detection */ 122 inline void removeErrorWatch() 123 { 124 return device.removeErrorWatch(); 125 } 126 127 /** @brief Starts to watch how many OCCs are present on the master */ 128 inline void addPresenceWatchMaster() 129 { 130 return device.addPresenceWatchMaster(); 131 } 132 133 private: 134 /** @brief sdbus handle */ 135 sdbusplus::bus::bus& bus; 136 137 /** @brief OCC dbus object path */ 138 std::string path; 139 140 /** @brief Callback handler to be invoked during property change. 141 * This is a handler in Manager class 142 */ 143 std::function<void(bool)> callBack; 144 145 /** @brief OCC instance number. Ex, 0,1, etc */ 146 int instance; 147 148 /** @brief OCC instance to Sensor definitions mapping */ 149 static const std::map<instanceID, sensorDefs> sensorMap; 150 151 /** @brief OCC device object to do bind and unbind */ 152 Device device; 153 154 /** @brief Subscribe to host control signal 155 * 156 * Once the OCC reset is requested, BMC sends that message to host. 157 * If the host does not ack the message, then there would be a timeout 158 * and we need to catch that to log an error 159 **/ 160 sdbusplus::bus::match_t hostControlSignal; 161 162 /** @brief Callback handler when device errors are detected 163 * 164 * @param[in] error - True if an error is reported, false otherwise 165 */ 166 void deviceErrorHandler(bool error); 167 168 /** @brief Callback function on host control signals 169 * 170 * @param[in] msg - Data associated with subscribed signal 171 */ 172 void hostControlEvent(sdbusplus::message::message& msg); 173 174 /** @brief Sends a message to host control command handler to reset OCC 175 */ 176 void resetOCC(); 177 178 /** @brief Determines the instance ID by specified object path. 179 * @param[in] path Estimated OCC Dbus object path 180 * @return Instance number 181 */ 182 static int getInstance(const std::string& path) 183 { 184 return (path.empty() ? 0 : path.back() - '0'); 185 } 186 187 /** @brief Override the sensor name with name from the definition. 188 * @param[in] estimatedPath - Estimated OCC Dbus object path 189 * @return Fixed OCC DBus object path 190 */ 191 static std::string getDbusPath(const std::string& estimatedPath) 192 { 193 if (!estimatedPath.empty()) 194 { 195 auto it = sensorMap.find(getInstance(estimatedPath)); 196 if (sensorMap.end() != it) 197 { 198 auto& name = std::get<1>(it->second); 199 if (!name.empty() && name != "None") 200 { 201 auto path = fs::path(estimatedPath); 202 path.replace_filename(name); 203 return path.string(); 204 } 205 } 206 } 207 208 return estimatedPath; 209 } 210 }; 211 212 } // namespace occ 213 } // namespace open_power 214