1 #include "occ_status.hpp" 2 3 #include "occ_sensor.hpp" 4 #include "utils.hpp" 5 6 #include <phosphor-logging/log.hpp> 7 namespace open_power 8 { 9 namespace occ 10 { 11 12 // Handles updates to occActive property 13 bool Status::occActive(bool value) 14 { 15 if (value != this->occActive()) 16 { 17 if (value) 18 { 19 // Bind the device 20 device.bind(); 21 22 // Start watching for errors 23 addErrorWatch(); 24 25 // Call into Manager to let know that we have bound 26 if (this->callBack) 27 { 28 this->callBack(value); 29 } 30 } 31 else 32 { 33 // Call into Manager to let know that we will unbind. 34 if (this->callBack) 35 { 36 this->callBack(value); 37 } 38 39 // Stop watching for errors 40 removeErrorWatch(); 41 42 // Do the unbind. 43 device.unBind(); 44 } 45 } 46 else if (value && !device.bound()) 47 { 48 // Existing error watch is on a dead file descriptor. 49 removeErrorWatch(); 50 51 /* 52 * In it's constructor, Status checks Device::bound() to see if OCC is 53 * active or not. 54 * Device::bound() checks for occX-dev0 directory. 55 * We will lose occX-dev0 directories during FSI rescan. 56 * So, if we start this application (and construct Status), and then 57 * later do FSI rescan, we will end up with occActive = true and device 58 * NOT bound. Lets correct that situation here. 59 */ 60 device.bind(); 61 62 // Add error watch again 63 addErrorWatch(); 64 } 65 return Base::Status::occActive(value); 66 } 67 68 // Callback handler when a device error is reported. 69 void Status::deviceErrorHandler(bool error) 70 { 71 // Make sure we have an error 72 if (error) 73 { 74 // This would deem OCC inactive 75 this->occActive(false); 76 77 // Reset the OCC 78 this->resetOCC(); 79 } 80 } 81 82 // Sends message to host control command handler to reset OCC 83 void Status::resetOCC() 84 { 85 using namespace phosphor::logging; 86 constexpr auto CONTROL_HOST_PATH = "/org/open_power/control/host0"; 87 constexpr auto CONTROL_HOST_INTF = "org.open_power.Control.Host"; 88 89 // This will throw exception on failure 90 auto service = getService(bus, CONTROL_HOST_PATH, CONTROL_HOST_INTF); 91 92 auto method = bus.new_method_call(service.c_str(), CONTROL_HOST_PATH, 93 CONTROL_HOST_INTF, "Execute"); 94 // OCC Reset control command 95 method.append(convertForMessage(Control::Host::Command::OCCReset).c_str()); 96 97 // OCC Sensor ID for callout reasons 98 method.append(sdbusplus::message::variant<uint8_t>( 99 std::get<0>(sensorMap.at(instance)))); 100 bus.call_noreply(method); 101 return; 102 } 103 104 // Handler called by Host control command handler to convey the 105 // status of the executed command 106 void Status::hostControlEvent(sdbusplus::message::message& msg) 107 { 108 using namespace phosphor::logging; 109 110 std::string cmdCompleted{}; 111 std::string cmdStatus{}; 112 113 msg.read(cmdCompleted, cmdStatus); 114 115 log<level::DEBUG>("Host control signal values", 116 entry("COMMAND=%s", cmdCompleted.c_str()), 117 entry("STATUS=%s", cmdStatus.c_str())); 118 119 if (Control::Host::convertResultFromString(cmdStatus) != 120 Control::Host::Result::Success) 121 { 122 if (Control::Host::convertCommandFromString(cmdCompleted) == 123 Control::Host::Command::OCCReset) 124 { 125 // Must be a Timeout. Log an Error trace 126 log<level::ERR>( 127 "Error resetting the OCC.", entry("PATH=%s", path.c_str()), 128 entry("SENSORID=0x%X", std::get<0>(sensorMap.at(instance)))); 129 } 130 } 131 return; 132 } 133 134 } // namespace occ 135 } // namespace open_power 136