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>(sensorMap.at(instance))); 99 bus.call_noreply(method); 100 return; 101 } 102 103 // Handler called by Host control command handler to convey the 104 // status of the executed command 105 void Status::hostControlEvent(sdbusplus::message::message& msg) 106 { 107 using namespace phosphor::logging; 108 109 std::string cmdCompleted{}; 110 std::string cmdStatus{}; 111 112 msg.read(cmdCompleted, cmdStatus); 113 114 log<level::DEBUG>("Host control signal values", 115 entry("COMMAND=%s", cmdCompleted.c_str()), 116 entry("STATUS=%s", cmdStatus.c_str())); 117 118 if (Control::Host::convertResultFromString(cmdStatus) != 119 Control::Host::Result::Success) 120 { 121 if (Control::Host::convertCommandFromString(cmdCompleted) == 122 Control::Host::Command::OCCReset) 123 { 124 // Must be a Timeout. Log an Error trace 125 log<level::ERR>("Error resetting the OCC.", 126 entry("PATH=%s", path.c_str()), 127 entry("SENSORID=0x%X", sensorMap.at(instance))); 128 } 129 } 130 return; 131 } 132 133 } // namespace occ 134 } // namespace open_power 135