diff options
author | Deepak Kumar Sahu <deepakx.sahu@intel.com> | 2019-05-20 14:58:58 +0000 |
---|---|---|
committer | Vernon Mauery <vernon.mauery@linux.intel.com> | 2019-09-10 23:39:02 +0000 |
commit | cfae948b82765c8dbaec809e0f13744e8dedb934 (patch) | |
tree | b6059a45953b8ef96d8c62f84b17bb74386b8347 | |
parent | 7dc4ac0246bfae3da04c11e7a2053d28acfde35c (diff) | |
download | phosphor-host-ipmid-cfae948b82765c8dbaec809e0f13744e8dedb934.tar.gz phosphor-host-ipmid-cfae948b82765c8dbaec809e0f13744e8dedb934.zip |
Watchdog: move get and set watchdog to new api.
Rewrite "get and set watchdog" command to use the newly
introduced ipmi api.
Tested:
Verified using ipmitool "get and set watchdog",
timer behavior is same before and after the changes.
Testing Procedure:
default watchdog timer is 11.2 seconds.
ipmitool raw 0x06 0x25 ---> Get
Output: 00 00 00 00 70 17 70 17
Note: Here 70 count(hex value)->112 count(decimal value)->112*100=11200ms
[100ms per count]->11.2sec (watchdog timer)
watchdog timer set to 20 seconds.
ipmitool raw 0x06 0x24 0x44 0x01 0x00 0x10 0xc8 0x00 ----> Set
output:
ipmitool raw 0x06 0x25 ---> Get
output: 04 01 00 00 c8 00 c8 00
Note: Here 20sec->20000ms->200count->c8 (hex value)
Signed-off-by: Deepak Kumar Sahu <deepakx.sahu@intel.com>
Change-Id: Id8c096bc1635d1900ee842a9726c49fb690fa8bc
-rw-r--r-- | app/watchdog.cpp | 188 | ||||
-rw-r--r-- | app/watchdog.hpp | 61 | ||||
-rw-r--r-- | app/watchdog_service.cpp | 5 | ||||
-rw-r--r-- | app/watchdog_service.hpp | 8 | ||||
-rw-r--r-- | apphandler.cpp | 10 |
5 files changed, 166 insertions, 106 deletions
diff --git a/app/watchdog.cpp b/app/watchdog.cpp index 25ca4b1..ff07b02 100644 --- a/app/watchdog.cpp +++ b/app/watchdog.cpp @@ -82,7 +82,12 @@ ipmi::RspType<> ipmiAppResetWatchdogTimer() 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 wdTimeoutActionTimer = 0x40; +static constexpr uint8_t wdTimeoutInterruptTimer = 0x04; enum class IpmiAction : uint8_t { @@ -168,55 +173,72 @@ WatchdogService::TimerUse ipmiTimerUseToWdTimerUse(IpmiTimerUse ipmiTimerUse) } } -struct wd_set_req -{ - uint8_t timer_use; - uint8_t timer_action; - uint8_t pretimeout; // (seconds) - uint8_t expire_flags; - uint16_t initial_countdown; // Little Endian (deciseconds) -} __attribute__((packed)); -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."); - -ipmi_ret_t ipmi_app_watchdog_set(ipmi_netfn_t netfn, ipmi_cmd_t cmd, - ipmi_request_t request, - ipmi_response_t response, - ipmi_data_len_t data_len, - ipmi_context_t context) +static uint8_t timerLogFlags = 0; +static uint8_t timerActions = 0; +static uint8_t timerUseExpirationFlags = 0; + +/**@brief The Set Watchdog Timer ipmi command. + * + * @param + * - timerUse + * - dontStopTimer + * - dontLog + * - timerAction + * - pretimeout + * - expireFlags + * - initialCountdown + * + * @return completion code on success. + **/ +ipmi::RspType<> ipmiSetWatchdogTimer( + uint3_t timerUse, uint3_t reserved, bool dontStopTimer, bool dontLog, + uint3_t timeoutAction, uint1_t reserved1, uint3_t preTimeoutInterrupt, + uint1_t reserved2, uint8_t preTimeoutInterval, uint1_t reserved3, + uint5_t expFlagValue, uint2_t reserved4, uint16_t initialCountdown) { - // Extract the request data - if (*data_len != sizeof(wd_set_req)) + if ((timerUse == wdTimerUseResTimer1) || + (timerUse == wdTimerUseResTimer2) || + (timerUse == wdTimerUseResTimer3) || + (timeoutAction == wdTimeoutActionTimer) || + (preTimeoutInterrupt == wdTimeoutInterruptTimer) || + (reserved1 | reserved2 | reserved3 | reserved4)) + { + return ipmi::responseInvalidFieldRequest(); + } + + if (preTimeoutInterval > (initialCountdown / 10)) { - *data_len = 0; - return IPMI_CC_REQ_DATA_LEN_INVALID; + return ipmi::responseInvalidFieldRequest(); } - wd_set_req req; - memcpy(&req, request, sizeof(req)); - req.initial_countdown = le16toh(req.initial_countdown); - *data_len = 0; + + timerLogFlags = static_cast<uint8_t>(dontLog); + timerActions &= static_cast<uint8_t>(timeoutAction) | + static_cast<uint8_t>(preTimeoutInterrupt) << 4; try { WatchdogService wd_service; // Stop the timer if the don't stop bit is not set - if (!(req.timer_use & wd_dont_stop)) + if (!(dontStopTimer)) { wd_service.setEnabled(false); } // Set the action based on the request - const auto ipmi_action = - static_cast<IpmiAction>(req.timer_action & wd_timeout_action_mask); + const auto ipmi_action = static_cast<IpmiAction>( + static_cast<uint8_t>(timeoutAction) & wd_timeout_action_mask); wd_service.setExpireAction(ipmiActionToWdAction(ipmi_action)); const auto ipmiTimerUse = - static_cast<IpmiTimerUse>(req.timer_use & wdTimerUseMask); + static_cast<IpmiTimerUse>(static_cast<uint8_t>(timerUse)); wd_service.setTimerUse(ipmiTimerUseToWdTimerUse(ipmiTimerUse)); + wd_service.setExpiredTimerUse(WatchdogService::TimerUse::Reserved); + + timerUseExpirationFlags &= static_cast<uint8_t>(~expFlagValue) << 2; + // Set the new interval and the time remaining deci -> mill seconds - const uint64_t interval = req.initial_countdown * 100; + const uint64_t interval = initialCountdown * 100; wd_service.setInterval(interval); wd_service.setTimeRemaining(interval); @@ -224,29 +246,29 @@ ipmi_ret_t ipmi_app_watchdog_set(ipmi_netfn_t netfn, ipmi_cmd_t cmd, wd_service.setInitialized(true); lastCallSuccessful = true; - return IPMI_CC_OK; + return ipmi::responseSuccess(); } catch (const std::domain_error&) { - return IPMI_CC_INVALID_FIELD_REQUEST; + return ipmi::responseInvalidFieldRequest(); } catch (const InternalFailure& e) { reportError(); - return IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } catch (const std::exception& e) { const std::string e_str = std::string("wd_set: ") + e.what(); log<level::ERR>(e_str.c_str()); reportError(); - return IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } catch (...) { log<level::ERR>("wd_set: Unknown Error"); reportError(); - return IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } } @@ -320,30 +342,30 @@ IpmiTimerUse wdTimerUseToIpmiTimerUse(WatchdogService::TimerUse wdTimerUse) } } -struct wd_get_res -{ - uint8_t timer_use; - uint8_t timer_action; - uint8_t pretimeout; - uint8_t expire_flags; - uint16_t initial_countdown; // Little Endian (deciseconds) - uint16_t present_countdown; // Little Endian (deciseconds) -} __attribute__((packed)); -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, - ipmi_request_t request, - ipmi_response_t response, - ipmi_data_len_t data_len, - ipmi_context_t context) +/**@brief The getWatchdogTimer ipmi command. + * + * @return Completion code plus timer details. + * - timerUse + * - timerAction + * - pretimeout + * - expireFlags + * - initialCountdown + * - presentCountdown + **/ +ipmi::RspType<uint8_t, // timerUse + uint8_t, // timerAction + uint8_t, // pretimeout + uint8_t, // expireFlags + uint16_t, // initial Countdown - Little Endian (deciseconds) + uint16_t // present Countdown - Little Endian (deciseconds) + > + ipmiGetWatchdogTimer() { - // Assume we will fail and send no data outside the return code - *data_len = 0; + uint8_t expireFlags = 0; + uint16_t presentCountdown = 0; + uint8_t pretimeout = 0; try { @@ -351,50 +373,68 @@ ipmi_ret_t ipmi_app_watchdog_get(ipmi_netfn_t netfn, ipmi_cmd_t cmd, WatchdogService::Properties wd_prop = wd_service.getProperties(); // 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)); + uint8_t timerUse = 0; + timerUse |= timerLogFlags; + + uint8_t timerAction = timerActions; // Interval and timeRemaining need converted from milli -> deci seconds - res.initial_countdown = htole16(wd_prop.interval / 100); + uint16_t initialCountdown = 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); + timerUse |= wd_running; + presentCountdown = htole16(wd_prop.timeRemaining / 100); + expireFlags = 0; } else { - res.present_countdown = res.initial_countdown; + if (wd_prop.expiredTimerUse == WatchdogService::TimerUse::Reserved) + { + presentCountdown = initialCountdown; + expireFlags = 0; + } + else + { + presentCountdown = 0; + expireFlags = timerUseExpirationFlags; + } } - res.timer_use |= + timerUse |= static_cast<uint8_t>(wdTimerUseToIpmiTimerUse(wd_prop.timerUse)); // TODO: Do something about having pretimeout support - res.pretimeout = 0; - res.expire_flags = 0; - memcpy(response, &res, sizeof(res)); - *data_len = sizeof(res); + pretimeout = 0; + lastCallSuccessful = true; - return IPMI_CC_OK; + return ipmi::responseSuccess(timerUse, timerAction, pretimeout, + expireFlags, initialCountdown, + presentCountdown); } catch (const InternalFailure& e) { reportError(); - return IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } catch (const std::exception& e) { const std::string e_str = std::string("wd_get: ") + e.what(); log<level::ERR>(e_str.c_str()); reportError(); - return IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } catch (...) { log<level::ERR>("wd_get: Unknown Error"); reportError(); - return IPMI_CC_UNSPECIFIED_ERROR; + return ipmi::responseUnspecifiedError(); } } diff --git a/app/watchdog.hpp b/app/watchdog.hpp index 3f91f4f..d52b6e6 100644 --- a/app/watchdog.hpp +++ b/app/watchdog.hpp @@ -6,35 +6,40 @@ */ ipmi::RspType<> ipmiAppResetWatchdogTimer(); -/** @brief The SET watchdog IPMI command. +/**@brief The setWatchdogTimer ipmi command. * - * @param[in] netfn - * @param[in] cmd - * @param[in] request - * @param[in,out] response - * @param[out] data_len - * @param[in] context + * @param + * - timerUse + * - dontStopTimer + * - dontLog + * - timerAction + * - pretimeout + * - expireFlags + * - initialCountdown * - * @return IPMI_CC_OK on success, an IPMI error code otherwise. - */ -ipmi_ret_t ipmi_app_watchdog_set(ipmi_netfn_t netfn, ipmi_cmd_t cmd, - ipmi_request_t request, - ipmi_response_t response, - ipmi_data_len_t data_len, - ipmi_context_t context); + * @return completion code on success. + **/ +ipmi::RspType<> ipmiSetWatchdogTimer( + uint3_t timerUse, uint3_t reserved, bool dontStopTimer, bool dontLog, + uint3_t timeoutAction, uint1_t reserved1, uint3_t preTimeoutInterrupt, + uint1_t reserved2, uint8_t preTimeoutInterval, uint1_t reserved3, + uint5_t expFlagValue, uint2_t reserved4, uint16_t initialCountdown); -/** @brief The GET watchdog IPMI command. - * @param[in] netfn - * @param[in] cmd - * @param[in] request - * @param[in,out] response - * @param[out] data_len - * @param[in] context +/**@brief The getWatchdogTimer ipmi command. * - * @return IPMI_CC_OK on success, an IPMI error code otherwise. - */ -ipmi_ret_t ipmi_app_watchdog_get(ipmi_netfn_t netfn, ipmi_cmd_t cmd, - ipmi_request_t request, - ipmi_response_t response, - ipmi_data_len_t data_len, - ipmi_context_t context); + * @return + * - timerUse + * - timerActions + * - pretimeout + * - timeruseFlags + * - initialCountdown + * - presentCountdown + **/ +ipmi::RspType<uint8_t, // timerUse + uint8_t, // timerAction + uint8_t, // pretimeout + uint8_t, // expireFlags + uint16_t, // initial Countdown - Little Endian (deciseconds) + uint16_t // present Countdown - Little Endian (deciseconds) + > + ipmiGetWatchdogTimer(); diff --git a/app/watchdog_service.cpp b/app/watchdog_service.cpp index 0b88369..c567ca9 100644 --- a/app/watchdog_service.cpp +++ b/app/watchdog_service.cpp @@ -186,6 +186,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 0cf1c74..ed64a3c 100644 --- a/app/watchdog_service.hpp +++ b/app/watchdog_service.hpp @@ -35,6 +35,7 @@ class WatchdogService bool enabled; Action expireAction; TimerUse timerUse; + TimerUse expiredTimerUse; uint64_t interval; uint64_t timeRemaining; }; @@ -78,6 +79,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 diff --git a/apphandler.cpp b/apphandler.cpp index a12e220..030031c 100644 --- a/apphandler.cpp +++ b/apphandler.cpp @@ -1243,12 +1243,14 @@ void register_netfn_app_functions() ipmi::Privilege::Operator, ipmiAppResetWatchdogTimer); // <Set Watchdog Timer> - ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_WD, NULL, - ipmi_app_watchdog_set, PRIVILEGE_OPERATOR); + ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, + ipmi::app::cmdSetWatchdogTimer, + ipmi::Privilege::Operator, ipmiSetWatchdogTimer); // <Get Watchdog Timer> - ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_WD, NULL, - ipmi_app_watchdog_get, PRIVILEGE_OPERATOR); + ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, + ipmi::app::cmdGetWatchdogTimer, + ipmi::Privilege::Operator, ipmiGetWatchdogTimer); // <Get Self Test Results> ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, |