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