diff options
author | Trevor Thompson <Trevor.Thompson@Sun.COM> | 2010-02-24 08:29:44 +0000 |
---|---|---|
committer | Trevor Thompson <Trevor.Thompson@Sun.COM> | 2010-02-24 08:29:44 +0000 |
commit | 8fc99e42676a23421c75e76660640f9765d693b1 (patch) | |
tree | 30d7a48022995f104d462a9b35944cf08a66338b | |
parent | d3b2efc749bec3b757d5f018cf78c9a09fa29cb3 (diff) | |
download | illumos-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.c | 6 | ||||
-rw-r--r-- | usr/src/uts/common/cpr/cpr_misc.c | 8 | ||||
-rw-r--r-- | usr/src/uts/common/os/clock.c | 156 | ||||
-rw-r--r-- | usr/src/uts/common/os/timers.c | 8 | ||||
-rw-r--r-- | usr/src/uts/common/sys/cpr.h | 6 | ||||
-rw-r--r-- | usr/src/uts/common/sys/systm.h | 10 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/hardclk.c | 12 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/todpc_subr.c | 7 | ||||
-rw-r--r-- | usr/src/uts/sun4u/io/hardclk.c | 17 | ||||
-rw-r--r-- | usr/src/uts/sun4u/io/todblade.c | 66 | ||||
-rw-r--r-- | usr/src/uts/sun4u/io/todds1337.c | 9 | ||||
-rw-r--r-- | usr/src/uts/sun4u/io/todm5819.c | 78 | ||||
-rw-r--r-- | usr/src/uts/sun4u/io/todm5819p_rmc.c | 93 | ||||
-rw-r--r-- | usr/src/uts/sun4u/io/todsg.c | 117 | ||||
-rw-r--r-- | usr/src/uts/sun4u/ngdr/io/dr_quiesce.c | 39 | ||||
-rw-r--r-- | usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c | 2 | ||||
-rw-r--r-- | usr/src/uts/sun4u/snowbird/io/todds1307/todds1307.c | 7 | ||||
-rw-r--r-- | usr/src/uts/sun4u/sunfire/io/sysctrl_quiesce.c | 36 | ||||
-rw-r--r-- | usr/src/uts/sun4v/io/hardclk.c | 16 |
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)®buf, &length); + (caddr_t)®buf, &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); } /* |