summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0057-Add-timer-use-actions-support.patch
blob: 5813cceaeace14d5c908c04ae4a468a0d28ad821 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
From 6e37e02a4f200507627a82f6dba00a9c9d877cb2 Mon Sep 17 00:00:00 2001
From: Yong Li <yong.b.li@linux.intel.com>
Date: Mon, 18 Mar 2019 23:05:16 +0800
Subject: [PATCH] Add timer use/actions support

Based on IPMI spec, add timer use/actions support,
and add input data checking

Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
---
 app/watchdog.cpp         | 62 +++++++++++++++++++++++++++++++++++++++++++-----
 app/watchdog_service.cpp |  8 +++++++
 app/watchdog_service.hpp |  8 +++++++
 3 files changed, 72 insertions(+), 6 deletions(-)

diff --git a/app/watchdog.cpp b/app/watchdog.cpp
index 1a5d19c..3b61055 100644
--- a/app/watchdog.cpp
+++ b/app/watchdog.cpp
@@ -89,6 +89,13 @@ static constexpr uint8_t wd_dont_stop = 0x1 << 6;
 static constexpr uint8_t wd_timeout_action_mask = 0x3;
 
 static constexpr uint8_t wdTimerUseMask = 0x7;
+static constexpr uint8_t wdTimerUseResTimer1 = 0x0;
+static constexpr uint8_t wdTimerUseResTimer2 = 0x6;
+static constexpr uint8_t wdTimerUseResTimer3 = 0x7;
+static constexpr uint8_t wdTimerUseRes = 0x38;
+
+static constexpr uint8_t wdTimerActionMask = 0xcc;
+static constexpr uint8_t wdTimerUseExpMask = 0xc1;
 
 enum class IpmiAction : uint8_t
 {
@@ -186,6 +193,11 @@ static_assert(sizeof(wd_set_req) == 6, "wd_set_req has invalid size.");
 static_assert(sizeof(wd_set_req) <= MAX_IPMI_BUFFER,
               "wd_get_res can't fit in request buffer.");
 
+static uint8_t timerLogFlags = 0;
+static uint8_t timerActions = 0;
+
+static uint8_t timerUseExpirationFlags = 0;
+
 ipmi_ret_t ipmi_app_watchdog_set(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                                  ipmi_request_t request,
                                  ipmi_response_t response,
@@ -203,6 +215,24 @@ ipmi_ret_t ipmi_app_watchdog_set(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
     req.initial_countdown = le16toh(req.initial_countdown);
     *data_len = 0;
 
+    if (((req.timer_use & wdTimerUseMask) == wdTimerUseResTimer1) ||
+        ((req.timer_use & wdTimerUseMask) == wdTimerUseResTimer2) ||
+        ((req.timer_use & wdTimerUseMask) == wdTimerUseResTimer3) ||
+        (req.timer_use & wdTimerUseRes) ||
+        (req.timer_action & wdTimerActionMask) ||
+        (req.expire_flags & wdTimerUseExpMask))
+    {
+        return IPMI_CC_INVALID_FIELD_REQUEST;
+    }
+
+    if (req.pretimeout > (req.initial_countdown / 10))
+    {
+        return IPMI_CC_INVALID_FIELD_REQUEST;
+    }
+
+    timerLogFlags = req.timer_use & 0x80;
+    timerActions = req.timer_action;
+
     try
     {
         WatchdogService wd_service;
@@ -221,6 +251,10 @@ ipmi_ret_t ipmi_app_watchdog_set(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
             static_cast<IpmiTimerUse>(req.timer_use & wdTimerUseMask);
         wd_service.setTimerUse(ipmiTimerUseToWdTimerUse(ipmiTimerUse));
 
+        wd_service.setExpiredTimerUse(WatchdogService::TimerUse::Reserved);
+
+        timerUseExpirationFlags &= ~req.expire_flags;
+
         // Set the new interval and the time remaining deci -> mill seconds
         const uint64_t interval = req.initial_countdown * 100;
         wd_service.setInterval(interval);
@@ -339,7 +373,6 @@ static_assert(sizeof(wd_get_res) == 8, "wd_get_res has invalid size.");
 static_assert(sizeof(wd_get_res) <= MAX_IPMI_BUFFER,
               "wd_get_res can't fit in response buffer.");
 
-static constexpr uint8_t wd_dont_log = 0x1 << 7;
 static constexpr uint8_t wd_running = 0x1 << 6;
 
 ipmi_ret_t ipmi_app_watchdog_get(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
@@ -358,20 +391,37 @@ ipmi_ret_t ipmi_app_watchdog_get(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
 
         // Build and return the response
         wd_get_res res;
-        res.timer_use = wd_dont_log;
-        res.timer_action =
-            static_cast<uint8_t>(wdActionToIpmiAction(wd_prop.expireAction));
+        res.timer_use |= timerLogFlags;
+        res.timer_action = timerActions;
 
         // Interval and timeRemaining need converted from milli -> deci seconds
         res.initial_countdown = htole16(wd_prop.interval / 100);
+
+        if (wd_prop.expiredTimerUse != WatchdogService::TimerUse::Reserved)
+        {
+            timerUseExpirationFlags |=
+                1 << static_cast<uint8_t>(
+                    wdTimerUseToIpmiTimerUse(wd_prop.expiredTimerUse));
+        }
+
         if (wd_prop.enabled)
         {
             res.timer_use |= wd_running;
             res.present_countdown = htole16(wd_prop.timeRemaining / 100);
+            res.expire_flags = 0;
         }
         else
         {
-            res.present_countdown = res.initial_countdown;
+            if (wd_prop.expiredTimerUse == WatchdogService::TimerUse::Reserved)
+            {
+                res.present_countdown = res.initial_countdown;
+                res.expire_flags = 0;
+            }
+            else
+            {
+                res.present_countdown = 0;
+                res.expire_flags = timerUseExpirationFlags;
+            }
         }
 
         res.timer_use |=
@@ -379,7 +429,7 @@ ipmi_ret_t ipmi_app_watchdog_get(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
 
         // TODO: Do something about having pretimeout support
         res.pretimeout = 0;
-        res.expire_flags = 0;
+
         memcpy(response, &res, sizeof(res));
         *data_len = sizeof(res);
         lastCallSuccessful = true;
diff --git a/app/watchdog_service.cpp b/app/watchdog_service.cpp
index e65ea63..8b1aa47 100644
--- a/app/watchdog_service.cpp
+++ b/app/watchdog_service.cpp
@@ -83,6 +83,9 @@ WatchdogService::Properties WatchdogService::getProperties()
         wd_prop.timerUse = Watchdog::convertTimerUseFromString(
             get<std::string>(properties.at("CurrentTimerUse")));
 
+        wd_prop.expiredTimerUse = Watchdog::convertTimerUseFromString(
+            get<std::string>(properties.at("ExpiredTimerUse")));
+
         wd_prop.interval = get<uint64_t>(properties.at("Interval"));
         wd_prop.timeRemaining = get<uint64_t>(properties.at("TimeRemaining"));
         return wd_prop;
@@ -187,6 +190,11 @@ void WatchdogService::setTimerUse(TimerUse timerUse)
     setProperty("CurrentTimerUse", convertForMessage(timerUse));
 }
 
+void WatchdogService::setExpiredTimerUse(TimerUse timerUse)
+{
+    setProperty("ExpiredTimerUse", convertForMessage(timerUse));
+}
+
 void WatchdogService::setInterval(uint64_t interval)
 {
     setProperty("Interval", interval);
diff --git a/app/watchdog_service.hpp b/app/watchdog_service.hpp
index 75afc1e..d0cc1a8 100644
--- a/app/watchdog_service.hpp
+++ b/app/watchdog_service.hpp
@@ -36,6 +36,7 @@ class WatchdogService
         bool enabled;
         Action expireAction;
         TimerUse timerUse;
+        TimerUse expiredTimerUse;
         uint64_t interval;
         uint64_t timeRemaining;
     };
@@ -79,6 +80,13 @@ class WatchdogService
      */
     void setTimerUse(TimerUse timerUse);
 
+    /** @brief Sets the value of the ExpiredTimerUse property on the host
+     * watchdog
+     *
+     *  @param[in] timerUse - The new timerUse value
+     */
+    void setExpiredTimerUse(TimerUse timerUse);
+
     /** @brief Sets the value of the interval property on the host watchdog
      *
      *  @param[in] interval - The new interval value
-- 
2.7.4