Author: avg
Date: Wed Jan 10 17:35:00 2018
New Revision: 327775
URL: https://svnweb.freebsd.org/changeset/base/327775
Log:
  amdsbwd: fix handling of timeout values beyond the supported range
  
  The driver now fully observes watchdog(9) protocol.
  Previously a too large timeout was silently clamped while the correct
  behavior is to disable the watchdog and leave the error as is
  (i.e. to not report success).
  
  Also, previously a too small value caused the timer to stop while the
  correct behavior is to use the minimal supported value.
  
  MFC after:    2 weeks

Modified:
  head/sys/dev/amdsbwd/amdsbwd.c

Modified: head/sys/dev/amdsbwd/amdsbwd.c
==============================================================================
--- head/sys/dev/amdsbwd/amdsbwd.c      Wed Jan 10 17:25:08 2018        
(r327774)
+++ head/sys/dev/amdsbwd/amdsbwd.c      Wed Jan 10 17:35:00 2018        
(r327775)
@@ -210,21 +210,30 @@ static void
 amdsbwd_event(void *arg, unsigned int cmd, int *error)
 {
        struct amdsbwd_softc *sc = arg;
-       unsigned int timeout;
+       uint64_t timeout;
 
-       /* convert from power-of-two-ns to WDT ticks */
-       cmd &= WD_INTERVAL;
-       if (cmd < WD_TO_1SEC)
-               cmd = 0;
-       if (cmd) {
-               timeout = ((uint64_t)1 << (cmd - WD_TO_1MS)) / sc->ms_per_tick;
+       if (cmd != 0) {
+               timeout = 0;
+               cmd &= WD_INTERVAL;
+               if (cmd >= WD_TO_1MS) {
+                       timeout = (uint64_t)1 << (cmd - WD_TO_1MS);
+                       timeout = timeout / sc->ms_per_tick;
+               }
+               /* For a too short timeout use 1 tick. */
+               if (timeout == 0)
+                       timeout = 1;
+               /* For a too long timeout stop the timer. */
                if (timeout > sc->max_ticks)
-                       timeout = sc->max_ticks;
-               if (timeout != sc->timeout) {
+                       timeout = 0;
+       } else {
+               timeout = 0;
+       }
+
+       if (timeout != 0) {
+               if (timeout != sc->timeout)
                        amdsbwd_tmr_set(sc, timeout);
-                       if (!sc->active)
-                               amdsbwd_tmr_enable(sc);
-               }
+               if (!sc->active)
+                       amdsbwd_tmr_enable(sc);
                amdsbwd_tmr_reload(sc);
                *error = 0;
        } else {
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to