From ea2ef9931c822e8c52dbf3ee16f54a24693667a1 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Tue, 22 Mar 2016 06:24:52 +0000 Subject: [PATCH] Optimize IPMI watchdog patting. Set watchdog timer parameters only when they really need to be changed. In other cases just restart the timer with single Reset command instead of two (Set and Reset). From one side this visually reduces amount of CPU time burned in tight loop waiting while some slow BMC configures its watchdog hardware, that seems to be much more complicated task then just resetting the timer. From another side on some BMCs those slow Set commands sometimes tend to timeout, that leads to noisy log messages and even more CPU time burned, so avoiding them can provide even bigger bonuses. MFC after: 2 weeks --- sys/dev/ipmi/ipmi.c | 53 +++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/sys/dev/ipmi/ipmi.c b/sys/dev/ipmi/ipmi.c index 810171751f5..314d4d696c0 100644 --- a/sys/dev/ipmi/ipmi.c +++ b/sys/dev/ipmi/ipmi.c @@ -602,6 +602,20 @@ ipmi_polled_enqueue_request(struct ipmi_softc *sc, struct ipmi_request *req) * Watchdog event handler. */ +static int +ipmi_reset_watchdog(struct ipmi_softc *sc) +{ + struct ipmi_request *req; + int error; + + IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0), + IPMI_RESET_WDOG, 0, 0); + error = ipmi_submit_driver_request(sc, req, 0); + if (error) + device_printf(sc->ipmi_dev, "Failed to reset watchdog\n"); + return (error); +} + static int ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec) { @@ -613,7 +627,6 @@ ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec) IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0), IPMI_SET_WDOG, 6, 0); - if (sec) { req->ir_request[0] = IPMI_SET_WD_TIMER_DONT_STOP | IPMI_SET_WD_TIMER_SMS_OS; @@ -630,24 +643,10 @@ ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec) req->ir_request[4] = 0; req->ir_request[5] = 0; } - error = ipmi_submit_driver_request(sc, req, 0); if (error) device_printf(sc->ipmi_dev, "Failed to set watchdog\n"); - else if (sec) { - IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0), - IPMI_RESET_WDOG, 0, 0); - - error = ipmi_submit_driver_request(sc, req, 0); - if (error) - device_printf(sc->ipmi_dev, - "Failed to reset watchdog\n"); - } - return (error); - /* - dump_watchdog(sc); - */ } static void @@ -665,12 +664,24 @@ ipmi_wd_event(void *arg, unsigned int cmd, int *error) timeout = ((uint64_t)1 << cmd) / 1000000000; if (timeout == 0) timeout = 1; - e = ipmi_set_watchdog(sc, timeout); - if (e == 0) { - *error = 0; - sc->ipmi_watchdog_active = 1; - } else - (void)ipmi_set_watchdog(sc, 0); + if (timeout != sc->ipmi_watchdog_active) { + e = ipmi_set_watchdog(sc, timeout); + if (e == 0) { + sc->ipmi_watchdog_active = timeout; + } else { + (void)ipmi_set_watchdog(sc, 0); + sc->ipmi_watchdog_active = 0; + } + } + if (sc->ipmi_watchdog_active != 0) { + e = ipmi_reset_watchdog(sc); + if (e == 0) { + *error = 0; + } else { + (void)ipmi_set_watchdog(sc, 0); + sc->ipmi_watchdog_active = 0; + } + } } else if (atomic_readandclear_int(&sc->ipmi_watchdog_active) != 0) { e = ipmi_set_watchdog(sc, 0); if (e != 0 && cmd == 0)