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