summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrevor Thompson <Trevor.Thompson@Sun.COM>2010-02-24 08:29:44 +0000
committerTrevor Thompson <Trevor.Thompson@Sun.COM>2010-02-24 08:29:44 +0000
commit8fc99e42676a23421c75e76660640f9765d693b1 (patch)
tree30d7a48022995f104d462a9b35944cf08a66338b
parentd3b2efc749bec3b757d5f018cf78c9a09fa29cb3 (diff)
downloadillumos-gate-8fc99e42676a23421c75e76660640f9765d693b1.tar.gz
6737518 tod_validate() may miss register corruption
6785049 todm5819p_rmc driver can generate time reversals of min/hour/day/etc minus 1 second 6923851 Tidy up complaints from 'hg pbchk' regarding several files.
-rw-r--r--usr/src/uts/common/cpr/cpr_main.c6
-rw-r--r--usr/src/uts/common/cpr/cpr_misc.c8
-rw-r--r--usr/src/uts/common/os/clock.c156
-rw-r--r--usr/src/uts/common/os/timers.c8
-rw-r--r--usr/src/uts/common/sys/cpr.h6
-rw-r--r--usr/src/uts/common/sys/systm.h10
-rw-r--r--usr/src/uts/i86pc/io/hardclk.c12
-rw-r--r--usr/src/uts/i86pc/io/todpc_subr.c7
-rw-r--r--usr/src/uts/sun4u/io/hardclk.c17
-rw-r--r--usr/src/uts/sun4u/io/todblade.c66
-rw-r--r--usr/src/uts/sun4u/io/todds1337.c9
-rw-r--r--usr/src/uts/sun4u/io/todm5819.c78
-rw-r--r--usr/src/uts/sun4u/io/todm5819p_rmc.c93
-rw-r--r--usr/src/uts/sun4u/io/todsg.c117
-rw-r--r--usr/src/uts/sun4u/ngdr/io/dr_quiesce.c39
-rw-r--r--usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c2
-rw-r--r--usr/src/uts/sun4u/snowbird/io/todds1307/todds1307.c7
-rw-r--r--usr/src/uts/sun4u/sunfire/io/sysctrl_quiesce.c36
-rw-r--r--usr/src/uts/sun4v/io/hardclk.c16
19 files changed, 425 insertions, 268 deletions
diff --git a/usr/src/uts/common/cpr/cpr_main.c b/usr/src/uts/common/cpr/cpr_main.c
index 31295e1b2c..68a4040186 100644
--- a/usr/src/uts/common/cpr/cpr_main.c
+++ b/usr/src/uts/common/cpr/cpr_main.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* This module contains the guts of checkpoint-resume mechanism.
* All code in this module is platform independent.
@@ -1044,7 +1042,7 @@ rb_mp_paused:
* Prevent false alarm in tod_validate() due to tod
* value change between suspend and resume
*/
- cpr_tod_fault_reset();
+ cpr_tod_status_set(TOD_CPR_RESUME_DONE);
cpr_convert_promtime(&pwron_tv);
diff --git a/usr/src/uts/common/cpr/cpr_misc.c b/usr/src/uts/common/cpr/cpr_misc.c
index 5db0eaa49d..1c862cdfc0 100644
--- a/usr/src/uts/common/cpr/cpr_misc.c
+++ b/usr/src/uts/common/cpr/cpr_misc.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/cpuvar.h>
@@ -851,10 +849,10 @@ cpr_tod_get(cpr_time_t *ctp)
}
void
-cpr_tod_fault_reset(void)
+cpr_tod_status_set(int tod_flag)
{
mutex_enter(&tod_lock);
- tod_fault_reset();
+ tod_status_set(tod_flag);
mutex_exit(&tod_lock);
}
diff --git a/usr/src/uts/common/os/clock.c b/usr/src/uts/common/os/clock.c
index 0f7982a80a..d481400a7d 100644
--- a/usr/src/uts/common/os/clock.c
+++ b/usr/src/uts/common/os/clock.c
@@ -330,7 +330,11 @@ static int lgrp_ticks; /* counter to schedule lgrp load calcs */
#define TOD_FILTER_N 4
#define TOD_FILTER_SETTLE (4 * TOD_FILTER_N)
static int tod_faulted = TOD_NOFAULT;
-static int tod_fault_reset_flag = 0;
+
+static int tod_status_flag = 0; /* used by tod_validate() */
+
+static hrtime_t prev_set_tick = 0; /* gethrtime() prior to tod_set() */
+static time_t prev_set_tod = 0; /* tv_sec value passed to tod_set() */
/* patchable via /etc/system */
int tod_validate_enable = 1;
@@ -2110,12 +2114,46 @@ tod_fault(enum tod_fault_type ftype, int off)
return (tod_faulted);
}
+/*
+ * Two functions that allow tod_status_flag to be manipulated by functions
+ * external to this file.
+ */
+
void
-tod_fault_reset()
+tod_status_set(int tod_flag)
{
- tod_fault_reset_flag = 1;
+ tod_status_flag |= tod_flag;
}
+void
+tod_status_clear(int tod_flag)
+{
+ tod_status_flag &= ~tod_flag;
+}
+
+/*
+ * Record a timestamp and the value passed to tod_set(). The next call to
+ * tod_validate() can use these values, prev_set_tick and prev_set_tod,
+ * when checking the timestruc_t returned by tod_get(). Ordinarily,
+ * tod_validate() will use prev_tick and prev_tod for this task but these
+ * become obsolete, and will be re-assigned with the prev_set_* values,
+ * in the case when the TOD is re-written.
+ */
+void
+tod_set_prev(timestruc_t ts)
+{
+ if ((tod_validate_enable == 0) || (tod_faulted != TOD_NOFAULT) ||
+ tod_validate_deferred) {
+ return;
+ }
+ prev_set_tick = gethrtime();
+ /*
+ * A negative value will be set to zero in utc_to_tod() so we fake
+ * a zero here in such a case. This would need to change if the
+ * behavior of utc_to_tod() changes.
+ */
+ prev_set_tod = ts.tv_sec < 0 ? 0 : ts.tv_sec;
+}
/*
* tod_validate() is used for checking values returned by tod_get().
@@ -2144,6 +2182,9 @@ tod_validate(time_t tod)
static hrtime_t prev_tick = 0;
static long dtick_avg = TOD_REF_FREQ;
+ int cpr_resume_done = 0;
+ int dr_resume_done = 0;
+
hrtime_t tick = gethrtime();
ASSERT(MUTEX_HELD(&tod_lock));
@@ -2159,7 +2200,9 @@ tod_validate(time_t tod)
}
/*
- * Update prev_tod and prev_tick values for first run
+ * If this is the first time through, we just need to save the tod
+ * we were called with and hrtime so we can use them next time to
+ * validate tod_get().
*/
if (firsttime) {
firsttime = 0;
@@ -2169,21 +2212,66 @@ tod_validate(time_t tod)
}
/*
- * For either of these conditions, we need to reset ourself
- * and start validation from zero since each condition
- * indicates that the TOD will be updated with new value
- * Also, note that tod_needsync will be reset in clock()
+ * Handle any flags that have been turned on by tod_status_set().
+ * In the case where a tod_set() is done and then a subsequent
+ * tod_get() fails (ie, both TOD_SET_DONE and TOD_GET_FAILED are
+ * true), we treat the TOD_GET_FAILED with precedence by switching
+ * off the flag, returning tod and leaving TOD_SET_DONE asserted
+ * until such time as tod_get() completes successfully.
*/
- if (tod_needsync || tod_fault_reset_flag) {
- firsttime = 1;
- prev_tod = 0;
- prev_tick = 0;
- dtick_avg = TOD_REF_FREQ;
-
- if (tod_fault_reset_flag)
- tod_fault_reset_flag = 0;
-
+ if (tod_status_flag & TOD_GET_FAILED) {
+ /*
+ * tod_get() has encountered an issue, possibly transitory,
+ * when reading TOD. We'll just return the incoming tod
+ * value (which is actually hrestime.tv_sec in this case)
+ * and when we get a genuine tod, following a successful
+ * tod_get(), we can validate using prev_tod and prev_tick.
+ */
+ tod_status_flag &= ~TOD_GET_FAILED;
return (tod);
+ } else if (tod_status_flag & TOD_SET_DONE) {
+ /*
+ * TOD has been modified. Just before the TOD was written,
+ * tod_set_prev() saved tod and hrtime; we can now use
+ * those values, prev_set_tod and prev_set_tick, to validate
+ * the incoming tod that's just been read.
+ */
+ prev_tod = prev_set_tod;
+ prev_tick = prev_set_tick;
+ dtick_avg = TOD_REF_FREQ;
+ tod_status_flag &= ~TOD_SET_DONE;
+ /*
+ * If a tod_set() preceded a cpr_suspend() without an
+ * intervening tod_validate(), we need to ensure that a
+ * TOD_JUMPED condition is ignored.
+ * Note this isn't a concern in the case of DR as we've
+ * just reassigned dtick_avg, above.
+ */
+ if (tod_status_flag & TOD_CPR_RESUME_DONE) {
+ cpr_resume_done = 1;
+ tod_status_flag &= ~TOD_CPR_RESUME_DONE;
+ }
+ } else if (tod_status_flag & TOD_CPR_RESUME_DONE) {
+ /*
+ * The system's coming back from a checkpoint resume.
+ */
+ cpr_resume_done = 1;
+ tod_status_flag &= ~TOD_CPR_RESUME_DONE;
+ /*
+ * We need to handle the possibility of a CPR suspend
+ * operation having been initiated whilst a DR event was
+ * in-flight.
+ */
+ if (tod_status_flag & TOD_DR_RESUME_DONE) {
+ dr_resume_done = 1;
+ tod_status_flag &= ~TOD_DR_RESUME_DONE;
+ }
+ } else if (tod_status_flag & TOD_DR_RESUME_DONE) {
+ /*
+ * A Dynamic Reconfiguration event has taken place.
+ */
+ dr_resume_done = 1;
+ tod_status_flag &= ~TOD_DR_RESUME_DONE;
}
/* test hook */
@@ -2254,12 +2342,34 @@ tod_validate(time_t tod)
*/
if (diff_tod > 4) {
if (dtick < TOD_JUMP_THRESHOLD) {
- /* ERROR - tod jumped */
- tod_bad = TOD_JUMPED;
- off = (int)diff_tod;
- } else if (dtick_delta) {
- /* ERROR - change in clock rate */
- tod_bad = TOD_RATECHANGED;
+ /*
+ * If we've just done a CPR resume, we detect
+ * a jump in the TOD but, actually, what's
+ * happened is that the TOD has been increasing
+ * whilst the system was suspended and the tick
+ * count hasn't kept up. We consider the first
+ * occurrence of this after a resume as normal
+ * and ignore it; otherwise, in a non-resume
+ * case, we regard it as a TOD problem.
+ */
+ if (!cpr_resume_done) {
+ /* ERROR - tod jumped */
+ tod_bad = TOD_JUMPED;
+ off = (int)diff_tod;
+ }
+ }
+ if (dtick_delta) {
+ /*
+ * If we've just done a DR resume, dtick_avg
+ * can go a bit askew so we reset it and carry
+ * on; otherwise, the TOD is in error.
+ */
+ if (dr_resume_done) {
+ dtick_avg = TOD_REF_FREQ;
+ } else {
+ /* ERROR - change in clock rate */
+ tod_bad = TOD_RATECHANGED;
+ }
}
}
}
diff --git a/usr/src/uts/common/os/timers.c b/usr/src/uts/common/os/timers.c
index 2fc7b7bff2..61acc6cf97 100644
--- a/usr/src/uts/common/os/timers.c
+++ b/usr/src/uts/common/os/timers.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1374,6 +1374,12 @@ utc_to_tod(time_t utc)
ASSERT(MUTEX_HELD(&tod_lock));
+ /*
+ * Note that tod_set_prev() assumes utc will be set to zero in
+ * the case of it being negative. Consequently, any change made
+ * to this behavior would have to be reflected in that function
+ * as well.
+ */
if (utc < 0) /* should never happen */
utc = 0;
diff --git a/usr/src/uts/common/sys/cpr.h b/usr/src/uts/common/sys/cpr.h
index 13230543f2..e88f711951 100644
--- a/usr/src/uts/common/sys/cpr.h
+++ b/usr/src/uts/common/sys/cpr.h
@@ -19,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_CPR_H
#define _SYS_CPR_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -651,7 +649,7 @@ extern void cpr_stat_event_print(void);
extern void cpr_stat_event_start(char *, cpr_time_t *);
extern void cpr_stat_record_events(void);
extern void cpr_tod_get(cpr_time_t *ctp);
-extern void cpr_tod_fault_reset(void);
+extern void cpr_tod_status_set(int);
extern void i_cpr_bitmap_cleanup(void);
extern void i_cpr_stop_other_cpus(void);
extern void i_cpr_alloc_cpus(void);
diff --git a/usr/src/uts/common/sys/systm.h b/usr/src/uts/common/sys/systm.h
index 4c3dc7f886..ca477d3746 100644
--- a/usr/src/uts/common/sys/systm.h
+++ b/usr/src/uts/common/sys/systm.h
@@ -23,7 +23,7 @@
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -134,8 +134,14 @@ enum tod_fault_type {
TOD_NOFAULT
};
+#define TOD_GET_FAILED 0x1 /* TOD could not be read */
+#define TOD_SET_DONE 0x2 /* TOD has been modified */
+#define TOD_CPR_RESUME_DONE 0x4 /* CPR resume has occurred */
+#define TOD_DR_RESUME_DONE 0x8 /* DR resume has occurred */
+
extern time_t tod_validate(time_t);
-extern void tod_fault_reset(void);
+extern void tod_status_set(int);
+extern void tod_status_clear(int);
extern void plat_tod_fault(enum tod_fault_type);
#ifndef _LP64
diff --git a/usr/src/uts/i86pc/io/hardclk.c b/usr/src/uts/i86pc/io/hardclk.c
index 590ff80f28..c24ea2bfad 100644
--- a/usr/src/uts/i86pc/io/hardclk.c
+++ b/usr/src/uts/i86pc/io/hardclk.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -28,8 +28,6 @@
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
/* All Rights Reserved */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/time.h>
#include <sys/systm.h>
@@ -49,6 +47,8 @@
char *tod_module_name; /* Settable in /etc/system */
+extern void tod_set_prev(timestruc_t);
+
/*
* Write the specified time into the clock chip.
* Must be called with tod_lock held.
@@ -58,11 +58,9 @@ tod_set(timestruc_t ts)
{
ASSERT(MUTEX_HELD(&tod_lock));
- /*
- * Prevent false alarm in tod_validate() due to tod value change.
- */
- tod_fault_reset();
+ tod_set_prev(ts); /* for tod_validate() */
TODOP_SET(tod_ops, ts);
+ tod_status_set(TOD_SET_DONE); /* TOD was modified */
}
/*
diff --git a/usr/src/uts/i86pc/io/todpc_subr.c b/usr/src/uts/i86pc/io/todpc_subr.c
index 251f13c6fe..244a8a8738 100644
--- a/usr/src/uts/i86pc/io/todpc_subr.c
+++ b/usr/src/uts/i86pc/io/todpc_subr.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -178,7 +178,7 @@ todpc_get(tod_ops_t *top)
if (todpc_rtcget((unsigned char *)&rtc)) {
ts.tv_sec = 0;
ts.tv_nsec = 0;
- tod_fault_reset();
+ tod_status_set(TOD_GET_FAILED);
return (ts);
}
@@ -214,6 +214,9 @@ todpc_get(tod_ops_t *top)
tod.tod_min = BCD_TO_BYTE(rtc.rtc_min);
tod.tod_sec = BCD_TO_BYTE(rtc.rtc_sec);
+ /* read was successful so ensure failure flag is clear */
+ tod_status_clear(TOD_GET_FAILED);
+
ts.tv_sec = tod_to_utc(tod) + ggmtl();
ts.tv_nsec = 0;
diff --git a/usr/src/uts/sun4u/io/hardclk.c b/usr/src/uts/sun4u/io/hardclk.c
index 1e36967fc9..f23dc248c4 100644
--- a/usr/src/uts/sun4u/io/hardclk.c
+++ b/usr/src/uts/sun4u/io/hardclk.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/time.h>
#include <sys/systm.h>
@@ -162,14 +159,14 @@ tod_get(void)
return (ts);
}
+extern void tod_set_prev(timestruc_t);
+
void
tod_set(timestruc_t ts)
{
- /*
- * Prevent false alarm in tod_validate() due to tod value change.
- */
- tod_fault_reset();
+ tod_set_prev(ts); /* for tod_validate() */
tod_ops.tod_set(ts);
+ tod_status_set(TOD_SET_DONE); /* TOD was modified */
}
diff --git a/usr/src/uts/sun4u/io/todblade.c b/usr/src/uts/sun4u/io/todblade.c
index aed8c769ac..3be6c1409d 100644
--- a/usr/src/uts/sun4u/io/todblade.c
+++ b/usr/src/uts/sun4u/io/todblade.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -93,10 +93,8 @@ _init(void)
tod_ops.tod_get = todbl_get;
tod_ops.tod_set = todbl_set;
- tod_ops.tod_set_watchdog_timer =
- todbl_set_watchdog_timer;
- tod_ops.tod_clear_watchdog_timer =
- todbl_clear_watchdog_timer;
+ tod_ops.tod_set_watchdog_timer = todbl_set_watchdog_timer;
+ tod_ops.tod_clear_watchdog_timer = todbl_clear_watchdog_timer;
tod_ops.tod_set_power_alarm = todbl_set_power_alarm;
tod_ops.tod_clear_power_alarm = todbl_clear_power_alarm;
tod_ops.tod_get_cpufrequency = todbl_get_cpufrequency;
@@ -155,8 +153,7 @@ todbl_get(void)
} else if (!watchdog_activated && watchdog_enable) {
(void) configure_wdog(WDOG_ON);
} else if (watchdog_activated &&
- (ddi_get_lbolt() - last_pat_lbt) >=
- SEC_TO_TICK(1)) {
+ (ddi_get_lbolt() - last_pat_lbt) >= SEC_TO_TICK(1)) {
/*
* PAT THE WATCHDOG!!
* We dont want to accelerate the pat frequency
@@ -184,15 +181,18 @@ todbl_get(void)
}
if (i == TODM5819_UIP_RETRY_THRESH) {
/*
- * We couldnt read from the tod
+ * We couldn't read from the TOD.
*/
- tod_fault_reset();
+ tod_status_set(TOD_GET_FAILED);
return (hrestime);
}
DPRINTF("todbl_get: century=%d year=%d dom=%d hrs=%d\n",
rtc.rtc_century, rtc.rtc_year, rtc.rtc_dom, rtc.rtc_hrs);
+ /* read was successful so ensure failure flag is clear */
+ tod_status_clear(TOD_GET_FAILED);
+
ts.tv_sec = tod_to_utc(rtc_to_tod(&rtc));
ts.tv_nsec = 0;
return (ts);
@@ -314,6 +314,7 @@ static void
write_rtc_time(struct rtc_t *rtc)
{
uint8_t regb;
+ int i;
/*
* Freeze
@@ -321,19 +322,40 @@ write_rtc_time(struct rtc_t *rtc)
regb = RTC_GET8(RTC_B);
RTC_PUT8(RTC_B, (regb | RTC_SET));
- RTC_PUT8(RTC_SEC, (rtc->rtc_sec));
- RTC_PUT8(RTC_ASEC, (rtc->rtc_asec));
- RTC_PUT8(RTC_MIN, (rtc->rtc_min));
- RTC_PUT8(RTC_AMIN, (rtc->rtc_amin));
-
- RTC_PUT8(RTC_HRS, (rtc->rtc_hrs));
- RTC_PUT8(RTC_AHRS, (rtc->rtc_ahrs));
- RTC_PUT8(RTC_DOW, (rtc->rtc_dow));
- RTC_PUT8(RTC_DOM, (rtc->rtc_dom));
-
- RTC_PUT8(RTC_MON, (rtc->rtc_mon));
- RTC_PUT8(RTC_YEAR, (rtc->rtc_year));
- RTC_PUT8(RTC_CENTURY, (rtc->rtc_century));
+ /*
+ * If an update is in progress wait for the UIP flag to clear.
+ * If we write whilst UIP is still set there is a slight but real
+ * possibility of corrupting the RTC date and time registers.
+ *
+ * The expected wait is one internal cycle of the chip. We could
+ * simply spin but this may hang a CPU if we were to have a broken
+ * RTC chip where UIP is stuck, so we use a retry loop instead.
+ * No critical section is needed here as the UIP flag will not be
+ * re-asserted until we clear RTC_SET.
+ */
+ for (i = 0; i < TODM5819_UIP_RETRY_THRESH; i++) {
+ if (!(RTC_GET8(RTC_A) & RTC_UIP)) {
+ break;
+ }
+ drv_usecwait(TODM5819_UIP_WAIT_USEC);
+ }
+ if (i < TODM5819_UIP_RETRY_THRESH) {
+ RTC_PUT8(RTC_SEC, (rtc->rtc_sec));
+ RTC_PUT8(RTC_ASEC, (rtc->rtc_asec));
+ RTC_PUT8(RTC_MIN, (rtc->rtc_min));
+ RTC_PUT8(RTC_AMIN, (rtc->rtc_amin));
+
+ RTC_PUT8(RTC_HRS, (rtc->rtc_hrs));
+ RTC_PUT8(RTC_AHRS, (rtc->rtc_ahrs));
+ RTC_PUT8(RTC_DOW, (rtc->rtc_dow));
+ RTC_PUT8(RTC_DOM, (rtc->rtc_dom));
+
+ RTC_PUT8(RTC_MON, (rtc->rtc_mon));
+ RTC_PUT8(RTC_YEAR, (rtc->rtc_year));
+ RTC_PUT8(RTC_CENTURY, (rtc->rtc_century));
+ } else {
+ cmn_err(CE_WARN, "todblade: Could not write the RTC\n");
+ }
/*
* Unfreeze
diff --git a/usr/src/uts/sun4u/io/todds1337.c b/usr/src/uts/sun4u/io/todds1337.c
index 09eb3b2ad7..319928bde7 100644
--- a/usr/src/uts/sun4u/io/todds1337.c
+++ b/usr/src/uts/sun4u/io/todds1337.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -386,7 +386,7 @@ todds1337_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
/*
* Read the current time from the DS1337 chip and convert to UNIX form.
- * Should be called with tod_clock held.
+ * Should be called with tod_lock held.
*/
static timestruc_t
@@ -402,7 +402,7 @@ todds1337_get(void)
(void) todds1337_read_rtc(&soft_rtc);
sync_clock_once = 0;
} else {
- tod_fault_reset();
+ tod_status_set(TOD_GET_FAILED);
return (hrestime);
}
@@ -422,6 +422,9 @@ todds1337_get(void)
tod.tod_min = rtc.rtc_min;
tod.tod_sec = rtc.rtc_sec;
+ /* read was successful so ensure failure flag is clear */
+ tod_status_clear(TOD_GET_FAILED);
+
ts.tv_sec = tod_to_utc(tod);
ts.tv_nsec = 0;
return (ts);
diff --git a/usr/src/uts/sun4u/io/todm5819.c b/usr/src/uts/sun4u/io/todm5819.c
index 24c20176c5..868acc62d9 100644
--- a/usr/src/uts/sun4u/io/todm5819.c
+++ b/usr/src/uts/sun4u/io/todm5819.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,15 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- */
-
#include <sys/types.h>
#include <sys/conf.h>
#include <sys/kmem.h>
@@ -86,15 +80,14 @@ int
_init(void)
{
if (strcmp(tod_module_name, "todm5819") == 0 ||
- strcmp(tod_module_name, "m5819") == 0) {
+ strcmp(tod_module_name, "m5819") == 0) {
RTC_PUT8(RTC_B, (RTC_DM | RTC_HM));
tod_ops.tod_get = todm5819_get;
tod_ops.tod_set = todm5819_set;
- tod_ops.tod_set_watchdog_timer =
- todm5819_set_watchdog_timer;
+ tod_ops.tod_set_watchdog_timer = todm5819_set_watchdog_timer;
tod_ops.tod_clear_watchdog_timer =
- todm5819_clear_watchdog_timer;
+ todm5819_clear_watchdog_timer;
tod_ops.tod_set_power_alarm = todm5819_set_power_alarm;
tod_ops.tod_clear_power_alarm = todm5819_clear_power_alarm;
tod_ops.tod_get_cpufrequency = todm5819_get_cpufrequency;
@@ -121,7 +114,7 @@ int
_fini(void)
{
if (strcmp(tod_module_name, "m5819") == 0 ||
- strcmp(tod_module_name, "todm5819") == 0) {
+ strcmp(tod_module_name, "todm5819") == 0) {
return (EBUSY);
} else {
return (mod_remove(&modlinkage));
@@ -163,14 +156,17 @@ todm5819_get(void)
}
if (i == TODM5819_UIP_RETRY_THRESH) {
/*
- * We couldnt read from the tod
+ * We couldn't read from the TOD.
*/
- tod_fault_reset();
+ tod_status_set(TOD_GET_FAILED);
return (hrestime);
}
DPRINTF("todm5819_get: century=%d year=%d dom=%d hrs=%d\n",
- rtc.rtc_century, rtc.rtc_year, rtc.rtc_dom, rtc.rtc_hrs);
+ rtc.rtc_century, rtc.rtc_year, rtc.rtc_dom, rtc.rtc_hrs);
+
+ /* read was successful so ensure failure flag is clear */
+ tod_status_clear(TOD_GET_FAILED);
ts.tv_sec = tod_to_utc(rtc_to_tod(&rtc));
ts.tv_nsec = 0;
@@ -272,6 +268,7 @@ void
write_rtc_time(struct rtc_t *rtc)
{
uint8_t regb;
+ int i;
/*
* Freeze
@@ -279,19 +276,40 @@ write_rtc_time(struct rtc_t *rtc)
regb = RTC_GET8(RTC_B);
RTC_PUT8(RTC_B, (regb | RTC_SET));
- RTC_PUT8(RTC_SEC, (rtc->rtc_sec));
- RTC_PUT8(RTC_ASEC, (rtc->rtc_asec));
- RTC_PUT8(RTC_MIN, (rtc->rtc_min));
- RTC_PUT8(RTC_AMIN, (rtc->rtc_amin));
-
- RTC_PUT8(RTC_HRS, (rtc->rtc_hrs));
- RTC_PUT8(RTC_AHRS, (rtc->rtc_ahrs));
- RTC_PUT8(RTC_DOW, (rtc->rtc_dow));
- RTC_PUT8(RTC_DOM, (rtc->rtc_dom));
-
- RTC_PUT8(RTC_MON, (rtc->rtc_mon));
- RTC_PUT8(RTC_YEAR, (rtc->rtc_year));
- RTC_PUT8(RTC_CENTURY, (rtc->rtc_century));
+ /*
+ * If an update is in progress wait for the UIP flag to clear.
+ * If we write whilst UIP is still set there is a slight but real
+ * possibility of corrupting the RTC date and time registers.
+ *
+ * The expected wait is one internal cycle of the chip. We could
+ * simply spin but this may hang a CPU if we were to have a broken
+ * RTC chip where UIP is stuck, so we use a retry loop instead.
+ * No critical section is needed here as the UIP flag will not be
+ * re-asserted until we clear RTC_SET.
+ */
+ for (i = 0; i < TODM5819_UIP_RETRY_THRESH; i++) {
+ if (!(RTC_GET8(RTC_A) & RTC_UIP)) {
+ break;
+ }
+ drv_usecwait(TODM5819_UIP_WAIT_USEC);
+ }
+ if (i < TODM5819_UIP_RETRY_THRESH) {
+ RTC_PUT8(RTC_SEC, (rtc->rtc_sec));
+ RTC_PUT8(RTC_ASEC, (rtc->rtc_asec));
+ RTC_PUT8(RTC_MIN, (rtc->rtc_min));
+ RTC_PUT8(RTC_AMIN, (rtc->rtc_amin));
+
+ RTC_PUT8(RTC_HRS, (rtc->rtc_hrs));
+ RTC_PUT8(RTC_AHRS, (rtc->rtc_ahrs));
+ RTC_PUT8(RTC_DOW, (rtc->rtc_dow));
+ RTC_PUT8(RTC_DOM, (rtc->rtc_dom));
+
+ RTC_PUT8(RTC_MON, (rtc->rtc_mon));
+ RTC_PUT8(RTC_YEAR, (rtc->rtc_year));
+ RTC_PUT8(RTC_CENTURY, (rtc->rtc_century));
+ } else {
+ cmn_err(CE_WARN, "todm5819: Could not write the RTC\n");
+ }
/*
* Unfreeze
diff --git a/usr/src/uts/sun4u/io/todm5819p_rmc.c b/usr/src/uts/sun4u/io/todm5819p_rmc.c
index 9b925d932e..5e92bebd81 100644
--- a/usr/src/uts/sun4u/io/todm5819p_rmc.c
+++ b/usr/src/uts/sun4u/io/todm5819p_rmc.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -129,16 +129,8 @@ _info(struct modinfo *modinfop)
/*
- * todm5819p_rmc is normally called once a second, from the clock thread.
- * It may also be infrequently called from other contexts (eg. ddi framework),
- * in which case our counting to NBAD_READ_LIMIT may be a few seconds short
- * of the desired 15-minute timeframe; this slight inaccuracy is acceptable.
- */
-#define NBAD_READ_LIMIT (900) /* 15 minutes, in seconds */
-/*
* Read the current time from the clock chip and convert to UNIX form.
- * Checks the century, but otherwise assumes that the values in the clock
- * chip are valid.
+ * Assumes that the year in the clock chip is valid.
* Must be called with tod_lock held.
*/
static timestruc_t
@@ -148,7 +140,6 @@ todm5819p_rmc_get(void)
int s;
timestruc_t ts;
struct rtc_t rtc;
- static int nbad_reads = 0;
ASSERT(MUTEX_HELD(&tod_lock));
@@ -185,26 +176,12 @@ todm5819p_rmc_get(void)
/*
* tod is inaccessible: just return current software time
*/
- tod_fault_reset();
+ tod_status_set(TOD_GET_FAILED);
return (hrestime);
}
- DPRINTF("todm5819p_rmc_get: century=%d year=%d dom=%d hrs=%d\n",
- (int)rtc.rtc_century, (int)rtc.rtc_year, (int)rtc.rtc_dom,
- (int)rtc.rtc_hrs);
-
- /* detect and correct invalid century register data */
- if (rtc.rtc_century < 19) {
- DPRINTF(
- "todm5819p_rmc_get: century invalid (%d), returning 20\n",
- (int)rtc.rtc_century);
- rtc.rtc_century = 20;
- if (++nbad_reads == NBAD_READ_LIMIT) {
- nbad_reads = 0;
- cmn_err(CE_WARN, "todm5819p: realtime clock century "
- "register appears to be defective.");
- }
- }
+ /* read was successful so ensure failure flag is clear */
+ tod_status_clear(TOD_GET_FAILED);
ts.tv_sec = tod_to_utc(rtc_to_tod(&rtc));
ts.tv_nsec = 0;
@@ -288,10 +265,6 @@ todm5819p_rmc_set(timestruc_t ts)
rtc.rtc_min = (uint8_t)tod.tod_min;
rtc.rtc_sec = (uint8_t)tod.tod_sec;
- DPRINTF("todm5819p_rmc_set: century=%d year=%d dom=%d hrs=%d\n",
- (int)rtc.rtc_century, (int)rtc.rtc_year, (int)rtc.rtc_dom,
- (int)rtc.rtc_hrs);
-
write_rtc_time(&rtc);
set_time_msg.year = year - 1900;
@@ -312,6 +285,7 @@ void
write_rtc_time(struct rtc_t *rtc)
{
uint8_t regb;
+ int i;
/*
* Freeze
@@ -320,22 +294,45 @@ write_rtc_time(struct rtc_t *rtc)
regb = M5819P_DATA_REG;
M5819P_DATA_REG = (regb | RTC_SET);
- M5819P_ADDR_REG = RTC_SEC;
- M5819P_DATA_REG = rtc->rtc_sec;
- M5819P_ADDR_REG = RTC_MIN;
- M5819P_DATA_REG = rtc->rtc_min;
- M5819P_ADDR_REG = RTC_HRS;
- M5819P_DATA_REG = rtc->rtc_hrs;
- M5819P_ADDR_REG = RTC_DOW;
- M5819P_DATA_REG = rtc->rtc_dow;
- M5819P_ADDR_REG = RTC_DOM;
- M5819P_DATA_REG = rtc->rtc_dom;
- M5819P_ADDR_REG = RTC_MON;
- M5819P_DATA_REG = rtc->rtc_mon;
- M5819P_ADDR_REG = RTC_YEAR;
- M5819P_DATA_REG = rtc->rtc_year;
- M5819P_ADDR_REG = RTC_CENTURY;
- M5819P_DATA_REG = rtc->rtc_century;
+ /*
+ * If an update cycle is in progress wait for the UIP flag to
+ * clear. If we write whilst UIP is still set there is a slight
+ * but real possibility of corrupting the RTC date and time
+ * registers.
+ *
+ * The expected wait is one internal cycle of the chip. We could
+ * simply spin but this may hang a CPU if we were to have a broken
+ * RTC chip where UIP is stuck, so we use a retry loop instead.
+ * No critical section is needed here as the UIP flag will not be
+ * re-asserted until we clear RTC_SET.
+ */
+ M5819P_ADDR_REG = RTC_A;
+ for (i = 0; i < TODM5819_UIP_RETRY_THRESH; i++) {
+ if (!(M5819P_DATA_REG & RTC_UIP)) {
+ break;
+ }
+ drv_usecwait(TODM5819_UIP_WAIT_USEC);
+ }
+ if (i < TODM5819_UIP_RETRY_THRESH) {
+ M5819P_ADDR_REG = RTC_SEC;
+ M5819P_DATA_REG = rtc->rtc_sec;
+ M5819P_ADDR_REG = RTC_MIN;
+ M5819P_DATA_REG = rtc->rtc_min;
+ M5819P_ADDR_REG = RTC_HRS;
+ M5819P_DATA_REG = rtc->rtc_hrs;
+ M5819P_ADDR_REG = RTC_DOW;
+ M5819P_DATA_REG = rtc->rtc_dow;
+ M5819P_ADDR_REG = RTC_DOM;
+ M5819P_DATA_REG = rtc->rtc_dom;
+ M5819P_ADDR_REG = RTC_MON;
+ M5819P_DATA_REG = rtc->rtc_mon;
+ M5819P_ADDR_REG = RTC_YEAR;
+ M5819P_DATA_REG = rtc->rtc_year;
+ M5819P_ADDR_REG = RTC_CENTURY;
+ M5819P_DATA_REG = rtc->rtc_century;
+ } else {
+ cmn_err(CE_WARN, "todm5819p_rmc: Could not write the RTC\n");
+ }
/*
* Unfreeze
diff --git a/usr/src/uts/sun4u/io/todsg.c b/usr/src/uts/sun4u/io/todsg.c
index 905715a221..344905a133 100644
--- a/usr/src/uts/sun4u/io/todsg.c
+++ b/usr/src/uts/sun4u/io/todsg.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -99,27 +99,26 @@ _init(void)
* Set the string to pass to OBP
*/
(void) sprintf(obp_string,
- "h# %p \" unix-get-tod\" $find if execute else "
- "3drop then",
- (void *)&ssc_time);
+ "h# %p \" unix-get-tod\" $find if execute else 3drop then",
+ (void *)&ssc_time);
prom_interpret(obp_string, 0, 0, 0, 0, 0);
if (ssc_time == (time_t)0) {
cmn_err(CE_WARN, "Initial date is invalid. "
- "This can be caused by older firmware.");
+ "This can be caused by older firmware.");
cmn_err(CE_CONT, "Please flashupdate the System "
- "Controller firmware to the latest version.\n");
+ "Controller firmware to the latest version.\n");
cmn_err(CE_CONT, "Attempting to set the date and time "
- "based on the last shutdown.\n");
+ "based on the last shutdown.\n");
cmn_err(CE_CONT, "Please inspect the date and time and "
- "correct if necessary.\n");
+ "correct if necessary.\n");
}
hrestime.tv_sec = ssc_time;
DCMNERR(CE_NOTE, "todsg: _init(): time from OBP 0x%lX",
- ssc_time);
+ ssc_time);
/*
* Verify whether the received date/clock has overflowed
* an integer(32bit), so that we capture any corrupted
@@ -128,9 +127,9 @@ _init(void)
if (TIMESPEC_OVERFLOW(&hrestime)) {
cmn_err(CE_WARN, "Date overflow detected.");
cmn_err(CE_CONT, "Attempting to set the date and time "
- "based on the last shutdown.\n");
+ "based on the last shutdown.\n");
cmn_err(CE_CONT, "Please inspect the date and time and "
- "correct if necessary.\n");
+ "correct if necessary.\n");
/*
* By setting hrestime.tv_sec to zero
@@ -187,7 +186,7 @@ update_heartbeat(void)
else
i_am_alive++;
if (iosram_write(SBBC_TOD_KEY, OFFSET(tod_buf, tod_i_am_alive),
- (char *)&i_am_alive, sizeof (uint32_t))) {
+ (char *)&i_am_alive, sizeof (uint32_t))) {
complained++;
cmn_err(CE_WARN, "update_heartbeat(): write heartbeat failed");
}
@@ -208,16 +207,16 @@ verify_sc_tod_version(void)
*/
if (!sc_tod_version || is_sc_down >= SC_DOWN_COUNT_THRESHOLD) {
if (iosram_read(SBBC_TOD_KEY, OFFSET(tod_buf, tod_magic),
- (char *)&magic, sizeof (uint32_t)) ||
- magic != TODSG_MAGIC) {
+ (char *)&magic, sizeof (uint32_t)) ||
+ magic != TODSG_MAGIC) {
cmn_err(CE_WARN, "get_sc_tod_version(): "
- "TOD SRAM magic error");
+ "TOD SRAM magic error");
return (FALSE);
}
if (iosram_read(SBBC_TOD_KEY, OFFSET(tod_buf, tod_version),
- (char *)&sc_tod_version, sizeof (uint32_t))) {
+ (char *)&sc_tod_version, sizeof (uint32_t))) {
cmn_err(CE_WARN, "get_sc_tod_version(): "
- "read tod version failed");
+ "read tod version failed");
sc_tod_version = 0;
return (FALSE);
}
@@ -226,10 +225,9 @@ verify_sc_tod_version(void)
return (TRUE);
} else {
todsg_use_sc = 0;
- cmn_err(CE_WARN,
- "todsg_get(): incorrect firmware version, "
- "(%d): expected version >= %d.",
- sc_tod_version, SC_TOD_MIN_REV);
+ cmn_err(CE_WARN, "todsg_get(): incorrect firmware version, "
+ "(%d): expected version >= %d.", sc_tod_version,
+ SC_TOD_MIN_REV);
}
return (FALSE);
}
@@ -244,27 +242,26 @@ update_tod_skew(time_t skew)
DCMNERR(CE_NOTE, "update_tod_skew(): skew 0x%lX", skew);
if (iosram_read(SBBC_TOD_KEY, OFFSET(tod_buf, tod_domain_skew),
- (char *)&domain_skew, sizeof (time_t))) {
+ (char *)&domain_skew, sizeof (time_t))) {
complained++;
- cmn_err(CE_WARN, "update_tod_skew(): "
- "read tod domain skew failed");
+ cmn_err(CE_WARN,
+ "update_tod_skew(): read tod domain skew failed");
}
domain_skew += skew;
/* we shall update the skew_adjust too now */
domain_skew += skew_adjust;
if (!complained && iosram_write(SBBC_TOD_KEY,
- OFFSET(tod_buf, tod_domain_skew),
- (char *)&domain_skew, sizeof (time_t))) {
+ OFFSET(tod_buf, tod_domain_skew), (char *)&domain_skew,
+ sizeof (time_t))) {
complained++;
- cmn_err(CE_WARN, "update_tod_skew(): "
- "write domain skew failed");
+ cmn_err(CE_WARN,
+ "update_tod_skew(): write domain skew failed");
}
if (!complained)
skew_adjust = 0;
return (complained);
}
-
/*
* Return time value read from IOSRAM.
* Must be called with tod_lock held.
@@ -287,8 +284,8 @@ todsg_get(void)
if (watchdog_activated != 0 || watchdog_enable != 0)
complained = update_heartbeat();
if (!complained && (iosram_read(SBBC_TOD_KEY,
- OFFSET(tod_buf, tod_get_value),
- (char *)&seconds, sizeof (time_t)))) {
+ OFFSET(tod_buf, tod_get_value), (char *)&seconds,
+ sizeof (time_t)))) {
complained++;
cmn_err(CE_WARN, "todsg_get(): read 64-bit tod value failed");
}
@@ -300,8 +297,8 @@ todsg_get(void)
complained = update_tod_skew(0);
}
if (!complained && iosram_read(SBBC_TOD_KEY,
- OFFSET(tod_buf, tod_domain_skew),
- (char *)&domain_skew, sizeof (time_t))) {
+ OFFSET(tod_buf, tod_domain_skew), (char *)&domain_skew,
+ sizeof (time_t))) {
complained++;
cmn_err(CE_WARN, "todsg_get(): read tod domain skew failed");
}
@@ -326,11 +323,11 @@ todsg_get(void)
skew_adjust = hrestime.tv_sec - (seconds + domain_skew);
complained = update_tod_skew(0);
if (!complained && (iosram_read(SBBC_TOD_KEY,
- OFFSET(tod_buf, tod_domain_skew),
- (char *)&domain_skew, sizeof (time_t)))) {
+ OFFSET(tod_buf, tod_domain_skew),
+ (char *)&domain_skew, sizeof (time_t)))) {
complained++;
cmn_err(CE_WARN, "todsg_get(): "
- "read tod domain skew failed");
+ "read tod domain skew failed");
}
}
is_sc_down = 0;
@@ -341,6 +338,11 @@ todsg_get(void)
* Hand back hrestime instead.
*/
if (!complained) {
+ /*
+ * The read was successful so ensure the failure
+ * flag is clear.
+ */
+ tod_status_clear(TOD_GET_FAILED);
timestruc_t ts = {0, 0};
ts.tv_sec = seconds + domain_skew;
return (ts);
@@ -357,11 +359,11 @@ todsg_get(void)
return_hrestime:
/*
- * We need to inform the tod_validate code to stop checking till
- * SC come back up again. Note that we will return hrestime below
- * which can be different that the previous TOD value we returned
+ * We need to inform the tod_validate() code to stop checking until
+ * the SC comes back up again. Note we will return hrestime below
+ * which may be different to the previous TOD value we returned.
*/
- tod_fault_reset();
+ tod_status_set(TOD_GET_FAILED);
return (hrestime);
}
@@ -404,15 +406,15 @@ todsg_set(timestruc_t ts)
* to update the skew.
*/
if (!complained && (iosram_read(SBBC_TOD_KEY,
- OFFSET(tod_buf, tod_get_value),
- (char *)&seconds, sizeof (time_t)))) {
+ OFFSET(tod_buf, tod_get_value), (char *)&seconds,
+ sizeof (time_t)))) {
complained++;
cmn_err(CE_WARN, "todsg_set(): read 64-bit tod value failed");
}
if (!complained && iosram_read(SBBC_TOD_KEY,
- OFFSET(tod_buf, tod_domain_skew),
- (char *)&domain_skew, sizeof (time_t))) {
+ OFFSET(tod_buf, tod_domain_skew), (char *)&domain_skew,
+ sizeof (time_t))) {
complained++;
cmn_err(CE_WARN, "todsg_set(): read tod domain skew failed");
}
@@ -426,8 +428,7 @@ todsg_set(timestruc_t ts)
complained = update_tod_skew(ts.tv_sec - hwtod);
DCMNERR(CE_NOTE, "todsg_set(): set time %lX (%lX)%s",
- ts.tv_sec, hwtod, complained ? " failed" : "");
-
+ ts.tv_sec, hwtod, complained ? " failed" : "");
}
if (complained) {
@@ -445,16 +446,16 @@ todsg_set_watchdog_timer(uint32_t timeoutval)
if (!verify_sc_tod_version()) {
DCMNERR(CE_NOTE, "todsg_set_watchdog_timer(): "
- "verify_sc_tod_version failed");
+ "verify_sc_tod_version failed");
return (0);
}
DCMNERR(CE_NOTE, "todsg_set_watchdog_timer(): "
- "set watchdog timer value = %d", timeoutval);
+ "set watchdog timer value = %d", timeoutval);
if (iosram_write(SBBC_TOD_KEY, OFFSET(tod_buf, tod_timeout_period),
- (char *)&timeoutval, sizeof (uint32_t))) {
+ (char *)&timeoutval, sizeof (uint32_t))) {
DCMNERR(CE_NOTE, "todsg_set_watchdog_timer(): "
- "write new timeout value failed");
+ "write new timeout value failed");
return (0);
}
watchdog_activated = 1;
@@ -472,23 +473,23 @@ todsg_clear_watchdog_timer(void)
if ((watchdog_activated == 0) || !verify_sc_tod_version()) {
DCMNERR(CE_NOTE, "todsg_set_watchdog_timer(): "
- "either watchdog not activated or "
- "verify_sc_tod_version failed");
+ "either watchdog not activated or "
+ "verify_sc_tod_version failed");
return (0);
}
if (iosram_read(SBBC_TOD_KEY, OFFSET(tod_buf, tod_timeout_period),
- (char *)&r_timeout_period, sizeof (uint32_t))) {
+ (char *)&r_timeout_period, sizeof (uint32_t))) {
DCMNERR(CE_NOTE, "todsg_clear_watchdog_timer(): "
- "read timeout value failed");
+ "read timeout value failed");
return (0);
}
DCMNERR(CE_NOTE, "todsg_clear_watchdog_timer(): "
- "clear watchdog timer (old value=%d)", r_timeout_period);
+ "clear watchdog timer (old value=%d)", r_timeout_period);
w_timeout_period = 0;
if (iosram_write(SBBC_TOD_KEY, OFFSET(tod_buf, tod_timeout_period),
- (char *)&w_timeout_period, sizeof (uint32_t))) {
+ (char *)&w_timeout_period, sizeof (uint32_t))) {
DCMNERR(CE_NOTE, "todsg_clear_watchdog_timer(): "
- "write zero timeout value failed");
+ "write zero timeout value failed");
return (0);
}
watchdog_activated = 0;
@@ -522,7 +523,7 @@ todsg_get_cpufrequency(void)
{
DCMNERR(CE_NOTE, "todsg_get_cpufrequency(): frequency=%ldMHz",
- cpunodes[CPU->cpu_id].clock_freq/1000000);
+ cpunodes[CPU->cpu_id].clock_freq/1000000);
return (cpunodes[CPU->cpu_id].clock_freq);
}
diff --git a/usr/src/uts/sun4u/ngdr/io/dr_quiesce.c b/usr/src/uts/sun4u/ngdr/io/dr_quiesce.c
index 392d1ed75c..f9bed6df8b 100644
--- a/usr/src/uts/sun4u/ngdr/io/dr_quiesce.c
+++ b/usr/src/uts/sun4u/ngdr/io/dr_quiesce.c
@@ -290,16 +290,16 @@ dr_check_dip(dev_info_t *dip, void *arg, uint_t ref)
if (dname && ((major = ddi_name_to_major(dname)) != (major_t)-1)) {
if (ref && rp->refcount) {
*rp->refcount += ref;
- PR_QR("\n %s (major# %d) is referenced(%u)\n",
- dname, major, ref);
+ PR_QR("\n %s (major# %d) is referenced(%u)\n", dname,
+ major, ref);
}
if (ref && rp->refcount_non_gldv3) {
if (NETWORK_PHYSDRV(major) && !GLDV3_DRV(major))
*rp->refcount_non_gldv3 += ref;
}
if (dr_is_unsafe_major(major) && i_ddi_devi_attached(dip)) {
- PR_QR("\n %s (major# %d) not hotpluggable\n",
- dname, major);
+ PR_QR("\n %s (major# %d) not hotpluggable\n", dname,
+ major);
if (rp->arr != NULL && rp->idx != NULL)
*rp->idx = dr_add_int(rp->arr, *rp->idx,
rp->len, (uint64_t)major);
@@ -389,8 +389,8 @@ dr_suspend_devices(dev_info_t *dip, dr_sr_handle_t *srh)
prom_printf("\tsuspending %s@%s (aka %s)\n",
d_name, d_info, d_alias);
} else {
- prom_printf("\tsuspending %s@%s\n",
- d_name, d_info);
+ prom_printf("\tsuspending %s@%s\n", d_name,
+ d_info);
}
} else {
prom_printf("\tsuspending %s@%s\n", dname, d_info);
@@ -440,8 +440,8 @@ dr_resume_devices(dev_info_t *start, dr_sr_handle_t *srh)
/* release hold acquired in dr_suspend_devices() */
srh->sr_failed_dip = NULL;
ndi_rele_devi(dip);
- } else
- if (dr_is_real_device(dip) && srh->sr_failed_dip == NULL) {
+ } else if (dr_is_real_device(dip) &&
+ srh->sr_failed_dip == NULL) {
if ((bn = ddi_binding_name(dip)) != NULL) {
major = ddi_name_to_major(bn);
@@ -457,19 +457,18 @@ dr_resume_devices(dev_info_t *start, dr_sr_handle_t *srh)
if (d_info == NULL)
d_info = "<null>";
- if (!dr_resolve_devname(dip, d_name,
- d_alias)) {
+ if (!dr_resolve_devname(dip, d_name, d_alias)) {
if (d_alias[0] != 0) {
prom_printf("\tresuming "
- "%s@%s (aka %s)\n",
- d_name, d_info, d_alias);
+ "%s@%s (aka %s)\n", d_name,
+ d_info, d_alias);
} else {
prom_printf("\tresuming "
"%s@%s\n", d_name, d_info);
}
} else {
- prom_printf("\tresuming %s@%s\n",
- bn, d_info);
+ prom_printf("\tresuming %s@%s\n", bn,
+ d_info);
}
if (devi_attach(dip, DDI_RESUME) !=
@@ -733,7 +732,7 @@ dr_resume(dr_sr_handle_t *srh)
* value change between suspend and resume
*/
mutex_enter(&tod_lock);
- tod_fault_reset();
+ tod_status_set(TOD_DR_RESUME_DONE);
mutex_exit(&tod_lock);
dr_enable_intr(); /* enable intr & clock */
@@ -972,14 +971,12 @@ dr_pt_test_suspend(dr_handle_t *hp)
PR_ALL("psmerr is ESBD_KTHREAD\n");
break;
default:
- PR_ALL("Resume error unknown = %d\n",
- psmerr);
+ PR_ALL("Resume error unknown = %d\n", psmerr);
break;
}
}
} else {
- PR_ALL("%s: dr_suspend() failed, err = 0x%x\n",
- f, err);
+ PR_ALL("%s: dr_suspend() failed, err = 0x%x\n", f, err);
psmerr = hp->h_err ? hp->h_err->e_code : ESBD_NOERROR;
switch (psmerr) {
case ESBD_UNSAFE:
@@ -1083,8 +1080,8 @@ drerr_int(int e_code, uint64_t *arr, int idx, int majors)
if (majors) {
dname = ddi_major_to_name(arr[i]);
if (dname) {
- n = snprintf(&buf[buf_idx], buf_avail,
- "%s, ", dname);
+ n = snprintf(&buf[buf_idx], buf_avail, "%s, ",
+ dname);
} else {
n = snprintf(&buf[buf_idx], buf_avail,
"major %lu, ", arr[i]);
diff --git a/usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c b/usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c
index 05cb27e648..2d6c28e1ee 100644
--- a/usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c
+++ b/usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c
@@ -694,7 +694,7 @@ sbdp_resume(sbdp_sr_handle_t *srh)
* value change between suspend and resume
*/
mutex_enter(&tod_lock);
- tod_fault_reset();
+ tod_status_set(TOD_DR_RESUME_DONE);
mutex_exit(&tod_lock);
sbdp_enable_intr(); /* enable intr & clock */
diff --git a/usr/src/uts/sun4u/snowbird/io/todds1307/todds1307.c b/usr/src/uts/sun4u/snowbird/io/todds1307/todds1307.c
index d9ff10f4d8..e0fd37ee04 100644
--- a/usr/src/uts/sun4u/snowbird/io/todds1307/todds1307.c
+++ b/usr/src/uts/sun4u/snowbird/io/todds1307/todds1307.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -380,7 +380,7 @@ todds1307_get(void)
(void) todds1307_read_rtc(&soft_rtc);
sync_clock_once = 0;
} else {
- tod_fault_reset();
+ tod_status_set(TOD_GET_FAILED);
return (hrestime);
}
@@ -400,6 +400,9 @@ todds1307_get(void)
tod.tod_min = rtc.rtc_min;
tod.tod_sec = rtc.rtc_sec;
+ /* read was successful so ensure failure flag is clear */
+ tod_status_clear(TOD_GET_FAILED);
+
ts.tv_sec = tod_to_utc(tod);
ts.tv_nsec = 0;
return (ts);
diff --git a/usr/src/uts/sun4u/sunfire/io/sysctrl_quiesce.c b/usr/src/uts/sun4u/sunfire/io/sysctrl_quiesce.c
index ff72a5e344..b9b091f759 100644
--- a/usr/src/uts/sun4u/sunfire/io/sysctrl_quiesce.c
+++ b/usr/src/uts/sun4u/sunfire/io/sysctrl_quiesce.c
@@ -20,12 +20,10 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* This workaround inhibits prom_printf after the cpus are grabbed.
* This can be removed when 4154263 is corrected.
@@ -124,10 +122,9 @@ sysctrl_grab_cpus(void)
others = cpu_ready_set;
CPUSET_DEL(others, CPU->cpu_id);
xt_some(others, (xcfunc_t *)sysctrl_freeze, (uint64_t)sysctrl_gate,
- (uint64_t)(&sysctrl_gate[CPU->cpu_id]));
+ (uint64_t)(&sysctrl_gate[CPU->cpu_id]));
- sysc_tick_limit =
- ((uint64_t)sys_tick_freq * SYSC_CPU_LOOP_MSEC) / 1000;
+ sysc_tick_limit = ((uint64_t)sys_tick_freq * SYSC_CPU_LOOP_MSEC) / 1000;
/* wait for each cpu to check in */
for (i = 0; i < NCPU; i++) {
@@ -148,8 +145,8 @@ sysctrl_grab_cpus(void)
/* Panic the system if cpu not responsed by deadline */
sysc_current_tick = gettick();
if (sysc_current_tick >= sysc_tick_deadline) {
- cmn_err(CE_PANIC, "sysctrl: cpu %d not "
- "responding to quiesce command", i);
+ cmn_err(CE_PANIC, "sysctrl: cpu %d not "
+ "responding to quiesce command", i);
}
}
}
@@ -204,7 +201,7 @@ sysctrl_is_real_device(dev_info_t *dip)
* now the general case
*/
rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
- (caddr_t)&regbuf, &length);
+ (caddr_t)&regbuf, &length);
ASSERT(rc != DDI_PROP_NO_MEMORY);
if (rc != DDI_PROP_SUCCESS) {
return (FALSE);
@@ -247,10 +244,10 @@ sysctrl_suspend_devices(dev_info_t *dip, sysc_cfga_pkt_t *pkt)
DEBUGP(errp(" suspending device %s\n", device_path));
if (devi_detach(dip, DDI_SUSPEND) != DDI_SUCCESS) {
DEBUGP(errp(" unable to suspend device %s\n",
- device_path));
+ device_path));
(void) strncpy(pkt->errbuf, device_path,
- SYSC_OUTPUT_LEN);
+ SYSC_OUTPUT_LEN);
SYSC_ERR_SET(pkt, SYSC_ERR_SUSPEND);
ndi_hold_devi(dip);
failed_driver = dip;
@@ -297,7 +294,7 @@ sysctrl_resume_devices(dev_info_t *start, sysc_cfga_pkt_t *pkt)
* cfgadm platform library.
*/
cmn_err(CE_PANIC, "Unable to resume device %s",
- device_path);
+ device_path);
}
}
ndi_devi_enter(dip, &circ);
@@ -415,7 +412,7 @@ sysctrl_stop_user_threads(sysc_cfga_pkt_t *pkt)
/* nope, cache the details for later */
bcopy(p->p_user.u_psargs, cache_psargs,
- sizeof (cache_psargs));
+ sizeof (cache_psargs));
cache_tp = tp;
cache_t_state = tp->t_state;
bailout = 1;
@@ -433,9 +430,8 @@ sysctrl_stop_user_threads(sysc_cfga_pkt_t *pkt)
/* were we unable to stop all threads after a few tries? */
if (bailout) {
(void) sprintf(pkt->errbuf, "process: %s id: %d state: %x"
- " thread descriptor: %p",
- cache_psargs, (int)pid, cache_t_state,
- (void *)cache_tp);
+ " thread descriptor: %p", cache_psargs, (int)pid,
+ cache_t_state, (void *)cache_tp);
SYSC_ERR_SET(pkt, SYSC_ERR_UTHREAD);
@@ -568,7 +564,7 @@ sysctrl_resume(sysc_cfga_pkt_t *pkt)
* value change between suspend and resume
*/
mutex_enter(&tod_lock);
- tod_fault_reset();
+ tod_status_set(TOD_DR_RESUME_DONE);
mutex_exit(&tod_lock);
sysctrl_release_cpus();
@@ -581,7 +577,7 @@ sysctrl_resume(sysc_cfga_pkt_t *pkt)
if (sysc_watchdog_suspended) {
mutex_enter(&tod_lock);
tod_ops.tod_set_watchdog_timer(
- watchdog_timeout_seconds);
+ watchdog_timeout_seconds);
mutex_exit(&tod_lock);
}
@@ -590,7 +586,7 @@ sysctrl_resume(sysc_cfga_pkt_t *pkt)
*/
(void) callb_execute_class(CB_CL_CPR_RPC, CB_CODE_CPR_RESUME);
(void) callb_execute_class(CB_CL_CPR_CALLOUT,
- CB_CODE_CPR_RESUME);
+ CB_CODE_CPR_RESUME);
sysctrl_enable_intr();
/* FALLTHROUGH */
@@ -616,7 +612,7 @@ sysctrl_resume(sysc_cfga_pkt_t *pkt)
if (!sysctrl_skip_kernel_threads) {
DEBUGP(errp("starting kernel daemons..."));
(void) callb_execute_class(CB_CL_CPR_DAEMON,
- CB_CODE_CPR_RESUME);
+ CB_CODE_CPR_RESUME);
callb_unlock_table();
}
DEBUGP(errp("done\n"));
diff --git a/usr/src/uts/sun4v/io/hardclk.c b/usr/src/uts/sun4v/io/hardclk.c
index 5e20307aa5..4c3ce82e6b 100644
--- a/usr/src/uts/sun4v/io/hardclk.c
+++ b/usr/src/uts/sun4v/io/hardclk.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/time.h>
#include <sys/systm.h>
@@ -182,7 +180,7 @@ tod_get(void)
/*
* We timed out
*/
- tod_fault_reset();
+ tod_status_set(TOD_GET_FAILED);
ts.tv_sec = tod_validate(hrestime.tv_sec);
break;
@@ -197,6 +195,8 @@ tod_get(void)
return (ts);
}
+extern void tod_set_prev(timestruc_t);
+
/*ARGSUSED*/
void
tod_set(timestruc_t ts)
@@ -204,16 +204,22 @@ tod_set(timestruc_t ts)
int i;
uint64_t ret;
- tod_fault_reset();
+ /* for tod_validate() */
+ tod_set_prev(ts);
+
for (i = 0; i <= HV_TOD_RETRY_THRESH; i++) {
ret = hv_tod_set(ts.tv_sec);
if (ret != H_EWOULDBLOCK)
break;
drv_usecwait(HV_TOD_WAIT_USEC);
}
+
if (ret != H_EOK && ret != H_ENOTSUPPORTED && ret != H_EWOULDBLOCK)
cmn_err(CE_WARN,
"tod_set: Unknown error from hv_tod_set, err %lx", ret);
+ else
+ /* TOD was modified */
+ tod_status_set(TOD_SET_DONE);
}
/*