This is the same ioctl the rest of the watchdogs support. GETTIMELEFT returns the number of seconds in the countdown -- useful for testing whether the watchdog is functioning.
Signed-off-by: Ryan O'Leary <ryanole...@google.com> --- drivers/char/ipmi/ipmi_watchdog.c | 75 +++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 32c334e34d55..f253c8667395 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -456,6 +456,71 @@ static int ipmi_set_timeout(int do_heartbeat) return rv; } +static unsigned int __ipmi_get_timeout(struct ipmi_smi_msg *smi_msg, + struct ipmi_recv_msg *recv_msg, + int *countdown) +{ + struct kernel_ipmi_msg msg; + int rv = 0; + struct ipmi_system_interface_addr addr; + + + addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + addr.channel = IPMI_BMC_CHANNEL; + addr.lun = 0; + + msg.netfn = 0x06; + msg.cmd = IPMI_WDOG_GET_TIMER; + msg.data = NULL; + msg.data_len = 0; + rv = ipmi_request_supply_msgs(watchdog_user, + (struct ipmi_addr *) &addr, + 0, + &msg, + NULL, + smi_msg, + recv_msg, + 1); + if (rv) { + pr_warn("get timeout error: %d\n", rv); + return rv; + } + + wait_for_completion(&msg_wait); + + if (recv_msg->msg.data_len < 9) { + pr_warn("get timeout response size: %d (expected 9)\n", + recv_msg->msg.data_len); + return -EIO; + } + + if (recv_msg->msg.data[0] != 0) { + pr_warn("get timeout completion code error: %d\n", + recv_msg->msg.data[0]); + return -EIO; + } + + *countdown = WDOG_GET_TIMEOUT(recv_msg->msg.data[7], recv_msg->msg.data[8]); + + return rv; +} + +static int _ipmi_get_timeout(int *countdown) +{ + int rv; + + if (!watchdog_user) + return -ENODEV; + + atomic_set(&msg_tofree, 2); + + rv = __ipmi_get_timeout(&smi_msg, + &recv_msg, + countdown); + + return rv; +} + static atomic_t panic_done_count = ATOMIC_INIT(0); static void panic_smi_free(struct ipmi_smi_msg *msg) @@ -729,6 +794,16 @@ static int ipmi_ioctl(struct file *file, return -EFAULT; return 0; + case WDIOC_GETTIMELEFT: + val = 0; + i = _ipmi_get_timeout(&val); + if (i) + return i; + i = copy_to_user(argp, &val, sizeof(val)); + if (i) + return -EFAULT; + return 0; + default: return -ENOIOCTLCMD; } -- 2.31.0.rc2.261.g7f71774620-goog