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
This commit is contained in:
Alexander Motin 2016-03-22 06:24:52 +00:00
parent 1f0dfd9918
commit ea2ef9931c

View File

@ -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)