Date: Fri, 18 Dec 2009 12:10:42 +0000 (UTC) From: Ruslan Ermilov <ru@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r200666 - head/sys/dev/ipmi Message-ID: <200912181210.nBICAgjX090825@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ru Date: Fri Dec 18 12:10:42 2009 New Revision: 200666 URL: http://svn.freebsd.org/changeset/base/200666 Log: - Fixed incorrect watchdog timeout setting: MSB of a 2-byte value is obtained by dividing it by 256, not by 2550; also, one second is 10^9 nanoseconds, not 1800000000 nanoseconds. - Due to rounding error, setting watchdog to a really small timeout (<1 sec) was turning the watchdog off. It should set the watchdog to a small timeout instead. - Implemented error checking in ipmi_wd_event(), as required by watchdog(9). PR: kern/130512 Submitted by: Dmitrij Tejblum - Additionally, check that the timeout value is within the supported range, and if it's too large, act as required by watchdog(9). MFC after: 3 days Modified: head/sys/dev/ipmi/ipmi.c Modified: head/sys/dev/ipmi/ipmi.c ============================================================================== --- head/sys/dev/ipmi/ipmi.c Fri Dec 18 12:09:44 2009 (r200665) +++ head/sys/dev/ipmi/ipmi.c Fri Dec 18 12:10:42 2009 (r200666) @@ -588,12 +588,15 @@ ipmi_polled_enqueue_request(struct ipmi_ * Watchdog event handler. */ -static void -ipmi_set_watchdog(struct ipmi_softc *sc, int sec) +static int +ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec) { struct ipmi_request *req; int error; + if (sec > 0xffff / 10) + return (EINVAL); + req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0), IPMI_SET_WDOG, 6, 0); @@ -604,7 +607,7 @@ ipmi_set_watchdog(struct ipmi_softc *sc, req->ir_request[2] = 0; req->ir_request[3] = 0; /* Timer use */ req->ir_request[4] = (sec * 10) & 0xff; - req->ir_request[5] = (sec * 10) / 2550; + req->ir_request[5] = (sec * 10) >> 8; } else { req->ir_request[0] = IPMI_SET_WD_TIMER_SMS_OS; req->ir_request[1] = 0; @@ -617,8 +620,7 @@ ipmi_set_watchdog(struct ipmi_softc *sc, error = ipmi_submit_driver_request(sc, req, 0); if (error) device_printf(sc->ipmi_dev, "Failed to set watchdog\n"); - - if (error == 0 && sec) { + else if (sec) { ipmi_free_request(req); req = ipmi_alloc_driver_request(IPMI_ADDR(IPMI_APP_REQUEST, 0), @@ -631,6 +633,7 @@ ipmi_set_watchdog(struct ipmi_softc *sc, } ipmi_free_request(req); + return (error); /* dump_watchdog(sc); */ @@ -641,14 +644,22 @@ ipmi_wd_event(void *arg, unsigned int cm { struct ipmi_softc *sc = arg; unsigned int timeout; + int e; cmd &= WD_INTERVAL; if (cmd > 0 && cmd <= 63) { - timeout = ((uint64_t)1 << cmd) / 1800000000; - ipmi_set_watchdog(sc, timeout); - *error = 0; + timeout = ((uint64_t)1 << cmd) / 1000000000; + if (timeout == 0) + timeout = 1; + e = ipmi_set_watchdog(sc, timeout); + if (e == 0) + *error = 0; + else + (void)ipmi_set_watchdog(sc, 0); } else { - ipmi_set_watchdog(sc, 0); + e = ipmi_set_watchdog(sc, 0); + if (e != 0 && cmd == 0) + *error = EOPNOTSUPP; } }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200912181210.nBICAgjX090825>