Author: ian
Date: Mon Feb 12 17:41:11 2018
New Revision: 329173
URL: https://svnweb.freebsd.org/changeset/base/329173

Log:
  Add a new sysctl, debug.clock_do_io, to allow manully triggering a one-shot
  read or write of all registered realtime clocks.  In the read case, the
  values read are simply discarded.  For writes, there's no alternative but
  to actually write the current system time to the device.

Modified:
  head/sys/kern/subr_rtc.c

Modified: head/sys/kern/subr_rtc.c
==============================================================================
--- head/sys/kern/subr_rtc.c    Mon Feb 12 17:33:14 2018        (r329172)
+++ head/sys/kern/subr_rtc.c    Mon Feb 12 17:41:11 2018        (r329173)
@@ -80,6 +80,11 @@ static int show_io;
 SYSCTL_INT(_debug, OID_AUTO, clock_show_io, CTLFLAG_RWTUN, &show_io, 0,
     "Enable debug printing of RTC clock I/O; 1=reads, 2=writes, 3=both.");
 
+static int sysctl_clock_do_io(SYSCTL_HANDLER_ARGS);
+SYSCTL_PROC(_debug, OID_AUTO, clock_do_io, CTLTYPE_INT | CTLFLAG_RW,
+    0, 0, sysctl_clock_do_io, "I",
+    "Trigger one-time IO on RTC clocks; 1=read (and discard), 2=write");
+
 /* XXX: should be kern. now, it's no longer machdep.  */
 static int disable_rtc_set;
 SYSCTL_INT(_machdep, OID_AUTO, disable_rtc_set, CTLFLAG_RW, &disable_rtc_set,
@@ -280,6 +285,36 @@ clock_schedule(device_t clockdev, u_int offsetns)
        sx_xunlock(&rtc_list_lock);
 }
 
+static int
+read_clocks(struct timespec *ts, bool debug_read)
+{
+       struct rtc_instance *rtc;
+       int error;
+
+       error = ENXIO;
+       sx_xlock(&rtc_list_lock);
+       LIST_FOREACH(rtc, &rtc_list, rtc_entries) {
+               if ((error = CLOCK_GETTIME(rtc->clockdev, ts)) != 0)
+                       continue;
+               if (ts->tv_sec < 0 || ts->tv_nsec < 0) {
+                       error = EINVAL;
+                       continue;
+               }
+               if (!(rtc->flags & CLOCKF_GETTIME_NO_ADJ)) {
+                       timespecadd(ts, &rtc->resadj);
+                       ts->tv_sec += utc_offset();
+               }
+               if (!debug_read) {
+                       if (bootverbose)
+                               device_printf(rtc->clockdev,
+                                   "providing initial system time\n");
+                       break;
+               }
+       }
+       sx_xunlock(&rtc_list_lock);
+       return (error);
+}
+
 /*
  * Initialize the system time.  Must be called from a context which does not
  * restrict any locking or sleeping that clock drivers may need to do.
@@ -296,28 +331,9 @@ void
 inittodr(time_t base)
 {
        struct timespec ts;
-       struct rtc_instance *rtc;
        int error;
 
-       error = ENXIO;
-       sx_xlock(&rtc_list_lock);
-       LIST_FOREACH(rtc, &rtc_list, rtc_entries) {
-               if ((error = CLOCK_GETTIME(rtc->clockdev, &ts)) != 0)
-                       continue;
-               if (ts.tv_sec < 0 || ts.tv_nsec < 0) {
-                       error = EINVAL;
-                       continue;
-               }
-               if (!(rtc->flags & CLOCKF_GETTIME_NO_ADJ)) {
-                       timespecadd(&ts, &rtc->resadj);
-                       ts.tv_sec += utc_offset();
-               }
-               if (bootverbose)
-                       device_printf(rtc->clockdev,
-                           "providing initial system time\n");
-               break;
-       }
-       sx_xunlock(&rtc_list_lock);
+       error = read_clocks(&ts, false);
 
        /*
         * Do not report errors from each clock; it is expected that some clocks
@@ -379,4 +395,30 @@ resettodr(void)
                    &rtc->stask, -sbt, 0, C_PREL(31));
        }
        sx_xunlock(&rtc_list_lock);
+}
+
+static int
+sysctl_clock_do_io(SYSCTL_HANDLER_ARGS)
+{
+       struct timespec ts_discard;
+       int error, value;
+
+       value = 0;
+       error = sysctl_handle_int(oidp, &value, 0, req);
+       if (error != 0 || req->newptr == NULL)
+               return (error);
+
+       switch (value) {
+       case CLOCK_DBG_READ:
+               if (read_clocks(&ts_discard, true) == ENXIO)
+                       printf("No registered RTC clocks\n");
+               break;
+       case CLOCK_DBG_WRITE:
+               resettodr();
+               break;
+       default:
+                return (EINVAL);
+       }
+
+       return (0);
 }
_______________________________________________
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