xref: /openbmc/openpower-occ-control/occ_status.cpp (revision 3c1706a8c36f7d05299ca65e2f3dc9a3785566a6)
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