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 // OCC sysfs name prefix 35 const std::string sysfsName = "occ-hwmon"; 36 37 /** @class Status 38 * @brief Implementation of OCC Active Status 39 */ 40 class Status : public Interface 41 { 42 public: 43 Status() = delete; 44 ~Status() = default; 45 Status(const Status&) = delete; 46 Status& operator=(const Status&) = delete; 47 Status(Status&&) = default; 48 Status& operator=(Status&&) = default; 49 50 /** @brief Constructs the Status object and 51 * the underlying device object 52 * 53 * @param[in] bus - DBus bus to attach to 54 * @param[in] event - sd_event unique pointer reference 55 * @param[in] path - DBus object path 56 * @param[in] manager - OCC manager instance 57 * @param[in] callBack - Callback handler to invoke during 58 * property change 59 */ 60 Status(sdbusplus::bus::bus& bus, EventPtr& event, const char* path, 61 const Manager& manager, 62 std::function<void(bool)> callBack = nullptr) : 63 Interface(bus, path, true), 64 bus(bus), path(path), callBack(callBack), 65 instance(((this->path.back() - '0'))), 66 device(event, 67 #ifdef I2C_OCC 68 fs::path(DEV_PATH) / i2c_occ::getI2cDeviceName(path), 69 #else 70 fs::path(DEV_PATH) / 71 fs::path(sysfsName + "." + std::to_string(instance + 1)), 72 #endif 73 manager, *this, 74 std::bind(std::mem_fn(&Status::deviceErrorHandler), this, 75 std::placeholders::_1)), 76 hostControlSignal( 77 bus, 78 sdbusRule::type::signal() + sdbusRule::member("CommandComplete") + 79 sdbusRule::path("/org/open_power/control/host0") + 80 sdbusRule::interface("org.open_power.Control.Host") + 81 sdbusRule::argN(0, Control::convertForMessage( 82 Control::Host::Command::OCCReset)), 83 std::bind(std::mem_fn(&Status::hostControlEvent), this, 84 std::placeholders::_1)) 85 { 86 // Check to see if we have OCC already bound. If so, just set it 87 if (device.bound()) 88 { 89 this->occActive(true); 90 } 91 92 // Announce that we are ready 93 this->emit_object_added(); 94 } 95 96 /** @brief Since we are overriding the setter-occActive but not the 97 * getter-occActive, we need to have this using in order to 98 * allow passthrough usage of the getter-occActive 99 */ 100 using Base::Status::occActive; 101 102 /** @brief SET OccActive to True or False 103 * 104 * @param[in] value - Intended value 105 * 106 * @return - Updated value of the property 107 */ 108 bool occActive(bool value) override; 109 110 /** @brief Starts OCC error detection */ 111 inline void addErrorWatch() 112 { 113 return device.addErrorWatch(); 114 } 115 116 /** @brief Stops OCC error detection */ 117 inline void removeErrorWatch() 118 { 119 return device.removeErrorWatch(); 120 } 121 122 /** @brief Starts to watch how many OCCs are present on the master */ 123 inline void addPresenceWatchMaster() 124 { 125 return device.addPresenceWatchMaster(); 126 } 127 128 private: 129 /** @brief sdbus handle */ 130 sdbusplus::bus::bus& bus; 131 132 /** @brief OCC dbus object path */ 133 std::string path; 134 135 /** @brief Callback handler to be invoked during property change. 136 * This is a handler in Manager class 137 */ 138 std::function<void(bool)> callBack; 139 140 /** @brief OCC instance number. Ex, 0,1, etc */ 141 int instance; 142 143 /** @brief OCC instance to Sensor ID mapping */ 144 static const std::map<instanceID, sensorID> sensorMap; 145 146 /** @brief OCC device object to do bind and unbind */ 147 Device device; 148 149 /** @brief Subscribe to host control signal 150 * 151 * Once the OCC reset is requested, BMC sends that message to host. 152 * If the host does not ack the message, then there would be a timeout 153 * and we need to catch that to log an error 154 **/ 155 sdbusplus::bus::match_t hostControlSignal; 156 157 /** @brief Callback handler when device errors are detected 158 * 159 * @param[in] error - True if an error is reported, false otherwise 160 */ 161 void deviceErrorHandler(bool error); 162 163 /** @brief Callback function on host control signals 164 * 165 * @param[in] msg - Data associated with subscribed signal 166 */ 167 void hostControlEvent(sdbusplus::message::message& msg); 168 169 /** @brief Sends a message to host control command handler to reset OCC 170 */ 171 void resetOCC(); 172 }; 173 174 } // namespace occ 175 } // namespace open_power 176