xref: /titanic_50/usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * A CPR derivative specifically for sbd
31  */
32 
33 #include <sys/types.h>
34 #include <sys/systm.h>
35 #include <sys/machparam.h>
36 #include <sys/machsystm.h>
37 #include <sys/ddi.h>
38 #define	SUNDDI_IMPL
39 #include <sys/sunddi.h>
40 #include <sys/sunndi.h>
41 #include <sys/devctl.h>
42 #include <sys/time.h>
43 #include <sys/kmem.h>
44 #include <nfs/lm.h>
45 #include <sys/ddi_impldefs.h>
46 #include <sys/ndi_impldefs.h>
47 #include <sys/obpdefs.h>
48 #include <sys/cmn_err.h>
49 #include <sys/debug.h>
50 #include <sys/errno.h>
51 #include <sys/callb.h>
52 #include <sys/clock.h>
53 #include <sys/x_call.h>
54 #include <sys/cpuvar.h>
55 #include <sys/epm.h>
56 #include <sys/vfs.h>
57 
58 #ifdef DEBUG
59 #include <sys/note.h>
60 #endif
61 
62 #include <sys/promif.h>
63 #include <sys/conf.h>
64 #include <sys/cyclic.h>
65 
66 #include <sys/sbd_ioctl.h>
67 #include <sys/sbd.h>
68 #include <sys/sbdp_priv.h>
69 #include <sys/cpu_sgnblk_defs.h>
70 
71 static char *
72 sbdp_get_err_buf(sbd_error_t *ep)
73 {
74 	return (ep->e_rsc);
75 }
76 
77 extern void	e_ddi_enter_driver_list(struct devnames *dnp, int *listcnt);
78 extern void	e_ddi_exit_driver_list(struct devnames *dnp, int listcnt);
79 extern int	is_pseudo_device(dev_info_t *dip);
80 
81 extern kmutex_t	cpu_lock;
82 
83 static int	sbdp_is_real_device(dev_info_t *dip);
84 #ifdef DEBUG
85 static int	sbdp_bypass_device(char *dname);
86 #endif
87 static int	sbdp_check_dip(dev_info_t *dip, void *arg, uint_t ref);
88 
89 static int	sbdp_resolve_devname(dev_info_t *dip, char *buffer,
90 				char *alias);
91 
92 int sbdp_test_suspend(sbdp_handle_t *hp);
93 
94 #define	SR_STATE(srh)			((srh)->sr_suspend_state)
95 #define	SR_SET_STATE(srh, state)	(SR_STATE((srh)) = (state))
96 #define	SR_FAILED_DIP(srh)		((srh)->sr_failed_dip)
97 
98 #define	SR_FLAG_WATCHDOG	0x1
99 #define	SR_CHECK_FLAG(srh, flag)	((srh)->sr_flags & (flag))
100 #define	SR_SET_FLAG(srh, flag)		((srh)->sr_flags |= (flag))
101 #define	SR_CLEAR_FLAG(srh, flag)	((srh)->sr_flags &= ~(flag))
102 
103 #ifdef DEBUG
104 /*
105  * Just for testing. List of drivers to bypass when performing a suspend.
106  */
107 static char *sbdp_bypass_list[] = {
108 	/* "sgsbbc", this is an example when needed */
109 	""
110 };
111 #endif
112 
113 #define		SKIP_SYNC	/* bypass sync ops in sbdp_suspend */
114 
115 /*
116  * sbdp_skip_user_threads is used to control if user threads should
117  * be suspended.  If sbdp_skip_user_threads is true, the rest of the
118  * flags are not used; if it is false, sbdp_check_user_stop_result
119  * will be used to control whether or not we need to check suspend
120  * result, and sbdp_allow_blocked_threads will be used to control
121  * whether or not we allow suspend to continue if there are blocked
122  * threads.  We allow all combinations of sbdp_check_user_stop_result
123  * and sbdp_allow_block_threads, even though it might not make much
124  * sense to not allow block threads when we don't even check stop
125  * result.
126  */
127 static int	sbdp_skip_user_threads = 0;		/* default to FALSE */
128 static int	sbdp_check_user_stop_result = 1;	/* default to TRUE */
129 static int	sbdp_allow_blocked_threads = 1;		/* default to TRUE */
130 
131 
132 static void
133 sbdp_stop_intr(void)
134 {
135 	kpreempt_disable();
136 	cyclic_suspend();
137 }
138 
139 static void
140 sbdp_enable_intr(void)
141 {
142 	cyclic_resume();
143 	kpreempt_enable();
144 }
145 
146 sbdp_sr_handle_t *
147 sbdp_get_sr_handle(void)
148 {
149 	sbdp_sr_handle_t *srh;
150 	srh = kmem_zalloc(sizeof (sbdp_sr_handle_t), KM_SLEEP);
151 
152 	return (srh);
153 }
154 
155 void
156 sbdp_release_sr_handle(sbdp_sr_handle_t *srh)
157 {
158 	ASSERT(SR_FAILED_DIP(srh) == NULL);
159 	kmem_free((caddr_t)srh, sizeof (sbdp_sr_handle_t));
160 }
161 
162 static int
163 sbdp_is_real_device(dev_info_t *dip)
164 {
165 	struct regspec *regbuf = NULL;
166 	int length = 0;
167 	int rc;
168 
169 	if (ddi_get_driver(dip) == NULL)
170 		return (0);
171 
172 	if (DEVI(dip)->devi_pm_flags & (PMC_NEEDS_SR|PMC_PARENTAL_SR))
173 		return (1);
174 	if (DEVI(dip)->devi_pm_flags & PMC_NO_SR)
175 		return (0);
176 
177 	/*
178 	 * now the general case
179 	 */
180 	rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
181 		(caddr_t)&regbuf, &length);
182 	ASSERT(rc != DDI_PROP_NO_MEMORY);
183 	if (rc != DDI_PROP_SUCCESS) {
184 		return (0);
185 	} else {
186 		if ((length > 0) && (regbuf != NULL))
187 			kmem_free(regbuf, length);
188 		return (1);
189 	}
190 }
191 
192 #ifdef DEBUG
193 static int
194 sbdp_bypass_device(char *dname)
195 {
196 	int i;
197 	char **lname;
198 	/* check the bypass list */
199 	for (i = 0, lname = &sbdp_bypass_list[i]; **lname != '\0'; lname++) {
200 		SBDP_DBG_QR("Checking %s\n", *lname);
201 		if (strcmp(dname, sbdp_bypass_list[i++]) == 0)
202 			return (1);
203 	}
204 	return (0);
205 }
206 #endif
207 
208 static int
209 sbdp_resolve_devname(dev_info_t *dip, char *buffer, char *alias)
210 {
211 	major_t	devmajor;
212 	char	*aka, *name;
213 
214 	*buffer = *alias = 0;
215 
216 	if (dip == NULL)
217 		return (-1);
218 
219 	if ((name = ddi_get_name(dip)) == NULL)
220 		name = "<null name>";
221 
222 	aka = name;
223 
224 	if ((devmajor = ddi_name_to_major(aka)) != -1)
225 		aka = ddi_major_to_name(devmajor);
226 
227 	(void) strcpy(buffer, name);
228 
229 	if (strcmp(name, aka))
230 		(void) strcpy(alias, aka);
231 	else
232 		*alias = 0;
233 
234 	return (0);
235 }
236 
237 typedef struct sbdp_ref {
238 	int *refcount;
239 	sbd_error_t *sep;
240 } sbdp_ref_t;
241 
242 static int
243 sbdp_check_dip(dev_info_t *dip, void *arg, uint_t ref)
244 {
245 	char		*dname;
246 	sbdp_ref_t	*sbrp = (sbdp_ref_t *)arg;
247 
248 	if (dip == NULL)
249 		return (DDI_WALK_CONTINUE);
250 
251 	ASSERT(sbrp->sep != NULL);
252 	ASSERT(sbrp->refcount != NULL);
253 
254 	if (!sbdp_is_real_device(dip))
255 		return (DDI_WALK_CONTINUE);
256 
257 	dname = ddi_binding_name(dip);
258 
259 	if ((strcmp(dname, "pciclass,060940") == 0) || (strcmp(dname,
260 	    "pciclass,060980") == 0)) {
261 		(void) ddi_pathname(dip, sbdp_get_err_buf(sbrp->sep));
262 		sbdp_set_err(sbrp->sep, ESBD_BUSY, NULL);
263 		(*sbrp->refcount)++;
264 		return (DDI_WALK_TERMINATE);
265 	}
266 
267 #ifdef DEBUG
268 	if (sbdp_bypass_device(dname))
269 		return (DDI_WALK_CONTINUE);
270 #endif
271 
272 	if (ref) {
273 		(*sbrp->refcount)++;
274 		SBDP_DBG_QR("\n%s (major# %d) is referenced\n",
275 			dname, ddi_name_to_major(dname));
276 		(void) ddi_pathname(dip, sbdp_get_err_buf(sbrp->sep));
277 		sbdp_set_err(sbrp->sep, ESBD_BUSY, NULL);
278 		return (DDI_WALK_TERMINATE);
279 	}
280 	return (DDI_WALK_CONTINUE);
281 }
282 
283 void
284 sbdp_check_devices(dev_info_t *dip, int *refcount, sbd_error_t *sep)
285 {
286 	sbdp_ref_t sbr;
287 
288 	sbr.refcount = refcount;
289 	sbr.sep = sep;
290 
291 	ASSERT(e_ddi_branch_held(dip));
292 
293 	(void) e_ddi_branch_referenced(dip, sbdp_check_dip, &sbr);
294 }
295 
296 /*
297  * Starting from the root node suspend all devices in the device tree.
298  * Assumes that all devices have already been marked busy.
299  */
300 static int
301 sbdp_suspend_devices_(dev_info_t *dip, sbdp_sr_handle_t *srh)
302 {
303 	major_t	major;
304 	char	*dname;
305 
306 	for (; dip != NULL; dip = ddi_get_next_sibling(dip)) {
307 		char	d_name[40], d_alias[40], *d_info;
308 
309 		if (sbdp_suspend_devices_(ddi_get_child(dip), srh)) {
310 			return (ENXIO);
311 		}
312 
313 		if (!sbdp_is_real_device(dip))
314 			continue;
315 
316 		major = (major_t)-1;
317 		if ((dname = DEVI(dip)->devi_binding_name) != NULL)
318 			major = ddi_name_to_major(dname);
319 
320 #ifdef DEBUG
321 		if (sbdp_bypass_device(dname)) {
322 			SBDP_DBG_QR("bypassed suspend of %s (major# %d)\n",
323 			    dname, major);
324 			continue;
325 		}
326 #endif
327 
328 		if ((d_info = ddi_get_name_addr(dip)) == NULL)
329 			d_info = "<null>";
330 
331 		d_name[0] = 0;
332 		if (sbdp_resolve_devname(dip, d_name, d_alias) == 0) {
333 			if (d_alias[0] != 0) {
334 				SBDP_DBG_QR("\tsuspending %s@%s (aka %s)\n",
335 					d_name, d_info, d_alias);
336 			} else {
337 				SBDP_DBG_QR("\tsuspending %s@%s\n",
338 					d_name, d_info);
339 			}
340 		} else {
341 			SBDP_DBG_QR("\tsuspending %s@%s\n", dname, d_info);
342 		}
343 
344 		if (devi_detach(dip, DDI_SUSPEND) != DDI_SUCCESS) {
345 			(void) sprintf(sbdp_get_err_buf(&srh->sep),
346 			    "%d", major);
347 
348 			sbdp_set_err(&srh->sep, ESGT_SUSPEND, NULL);
349 			ndi_hold_devi(dip);
350 			SR_FAILED_DIP(srh) = dip;
351 			return (DDI_FAILURE);
352 		}
353 	}
354 
355 	return (DDI_SUCCESS);
356 }
357 
358 /*ARGSUSED*/
359 static int
360 sbdp_suspend_devices_enter(dev_info_t *dip, void *arg)
361 {
362 	struct dev_info *devi = DEVI(dip);
363 	ndi_devi_enter(dip, &devi->devi_circular);
364 	return (DDI_WALK_CONTINUE);
365 }
366 
367 /*ARGSUSED*/
368 static int
369 sbdp_suspend_devices_exit(dev_info_t *dip, void *arg)
370 {
371 	struct dev_info *devi = DEVI(dip);
372 	ndi_devi_exit(dip, devi->devi_circular);
373 	return (DDI_WALK_CONTINUE);
374 }
375 
376 /*
377  * Before suspending devices first mark all device nodes busy. This
378  * avoids a deadlock situation when another thread holds a device busy
379  * and accesses an already suspended device.
380  */
381 static int
382 sbdp_suspend_devices(dev_info_t *dip, sbdp_sr_handle_t *srh)
383 {
384 	int	rv;
385 
386 	/* assumes dip is ddi_root_node so no ndi_devi_enter required */
387 	ASSERT(dip == ddi_root_node());
388 	ddi_walk_devs(dip, sbdp_suspend_devices_enter, NULL);
389 	rv = sbdp_suspend_devices_(dip, srh);
390 	ddi_walk_devs(dip, sbdp_suspend_devices_exit, NULL);
391 	return (rv);
392 }
393 
394 static void
395 sbdp_resume_devices(dev_info_t *start, sbdp_sr_handle_t *srh)
396 {
397 	int circ;
398 	dev_info_t	*dip, *next, *last = NULL;
399 	char		*bn;
400 	sbd_error_t	*sep;
401 
402 	sep = &srh->sep;
403 
404 	/* attach in reverse device tree order */
405 	while (last != start) {
406 		dip = start;
407 		next = ddi_get_next_sibling(dip);
408 		while (next != last && dip != SR_FAILED_DIP(srh)) {
409 			dip = next;
410 			next = ddi_get_next_sibling(dip);
411 		}
412 		if (dip == SR_FAILED_DIP(srh)) {
413 			/* Release hold acquired in sbdp_suspend_devices() */
414 			ndi_rele_devi(dip);
415 			SR_FAILED_DIP(srh) = NULL;
416 		} else if (sbdp_is_real_device(dip) &&
417 				SR_FAILED_DIP(srh) == NULL) {
418 
419 			if (DEVI(dip)->devi_binding_name != NULL) {
420 				bn = ddi_binding_name(dip);
421 			}
422 #ifdef DEBUG
423 			if (!sbdp_bypass_device(bn)) {
424 #else
425 			{
426 #endif
427 				char	d_name[40], d_alias[40], *d_info;
428 
429 				d_name[0] = 0;
430 				d_info = ddi_get_name_addr(dip);
431 				if (d_info == NULL)
432 					d_info = "<null>";
433 
434 				if (!sbdp_resolve_devname(dip, d_name,
435 								d_alias)) {
436 					if (d_alias[0] != 0) {
437 						SBDP_DBG_QR("\tresuming "
438 							"%s@%s (aka %s)\n",
439 							d_name, d_info,
440 							d_alias);
441 					} else {
442 						SBDP_DBG_QR("\tresuming "
443 							"%s@%s\n",
444 							d_name, d_info);
445 					}
446 				} else {
447 					SBDP_DBG_QR("\tresuming %s@%s\n",
448 						bn, d_info);
449 				}
450 
451 				if (devi_attach(dip, DDI_RESUME) !=
452 							DDI_SUCCESS) {
453 					/*
454 					 * Print a console warning,
455 					 * set an errno of ESGT_RESUME,
456 					 * and save the driver major
457 					 * number in the e_str.
458 					 */
459 
460 					(void) sprintf(sbdp_get_err_buf(sep),
461 					    "%s@%s",
462 					    d_name[0] ? d_name : bn, d_info);
463 					SBDP_DBG_QR("\tFAILED to resume "
464 						"%s\n", sbdp_get_err_buf(sep));
465 					sbdp_set_err(sep,
466 					    ESGT_RESUME, NULL);
467 				}
468 			}
469 		}
470 		ndi_devi_enter(dip, &circ);
471 		sbdp_resume_devices(ddi_get_child(dip), srh);
472 		ndi_devi_exit(dip, circ);
473 		last = dip;
474 	}
475 }
476 
477 /*
478  * True if thread is virtually stopped.  Similar to CPR_VSTOPPED
479  * but from DR point of view.  These user threads are waiting in
480  * the kernel.  Once they return from kernel, they will process
481  * the stop signal and stop.
482  */
483 #define	SBDP_VSTOPPED(t)			\
484 	((t)->t_state == TS_SLEEP &&		\
485 	(t)->t_wchan != NULL &&			\
486 	(t)->t_astflag &&		\
487 	((t)->t_proc_flag & TP_CHKPT))
488 
489 
490 static int
491 sbdp_stop_user_threads(sbdp_sr_handle_t *srh)
492 {
493 	int		count;
494 	char		cache_psargs[PSARGSZ];
495 	kthread_id_t	cache_tp;
496 	uint_t		cache_t_state;
497 	int		bailout;
498 	sbd_error_t	*sep;
499 	kthread_id_t 	tp;
500 
501 	extern void add_one_utstop();
502 	extern void utstop_timedwait(clock_t);
503 	extern void utstop_init(void);
504 
505 #define	SBDP_UTSTOP_RETRY	4
506 #define	SBDP_UTSTOP_WAIT	hz
507 
508 	if (sbdp_skip_user_threads)
509 		return (DDI_SUCCESS);
510 
511 	sep = &srh->sep;
512 	ASSERT(sep);
513 
514 	utstop_init();
515 
516 	/* we need to try a few times to get past fork, etc. */
517 	for (count = 0; count < SBDP_UTSTOP_RETRY; count++) {
518 		/* walk the entire threadlist */
519 		mutex_enter(&pidlock);
520 		for (tp = curthread->t_next; tp != curthread; tp = tp->t_next) {
521 			proc_t *p = ttoproc(tp);
522 
523 			/* handle kernel threads separately */
524 			if (p->p_as == &kas || p->p_stat == SZOMB)
525 				continue;
526 
527 			mutex_enter(&p->p_lock);
528 			thread_lock(tp);
529 
530 			if (tp->t_state == TS_STOPPED) {
531 				/* add another reason to stop this thread */
532 				tp->t_schedflag &= ~TS_RESUME;
533 			} else {
534 				tp->t_proc_flag |= TP_CHKPT;
535 
536 				thread_unlock(tp);
537 				mutex_exit(&p->p_lock);
538 				add_one_utstop();
539 				mutex_enter(&p->p_lock);
540 				thread_lock(tp);
541 
542 				aston(tp);
543 
544 				if (ISWAKEABLE(tp) || ISWAITING(tp)) {
545 					setrun_locked(tp);
546 				}
547 			}
548 
549 			/* grab thread if needed */
550 			if (tp->t_state == TS_ONPROC && tp->t_cpu != CPU)
551 				poke_cpu(tp->t_cpu->cpu_id);
552 
553 
554 			thread_unlock(tp);
555 			mutex_exit(&p->p_lock);
556 		}
557 		mutex_exit(&pidlock);
558 
559 
560 		/* let everything catch up */
561 		utstop_timedwait(count * count * SBDP_UTSTOP_WAIT);
562 
563 
564 		/* now, walk the threadlist again to see if we are done */
565 		mutex_enter(&pidlock);
566 		for (tp = curthread->t_next, bailout = 0;
567 			tp != curthread; tp = tp->t_next) {
568 			proc_t *p = ttoproc(tp);
569 
570 			/* handle kernel threads separately */
571 			if (p->p_as == &kas || p->p_stat == SZOMB)
572 				continue;
573 
574 			/*
575 			 * If this thread didn't stop, and we don't allow
576 			 * unstopped blocked threads, bail.
577 			 */
578 			thread_lock(tp);
579 			if (!CPR_ISTOPPED(tp) &&
580 			    !(sbdp_allow_blocked_threads &&
581 			    SBDP_VSTOPPED(tp))) {
582 
583 				/* nope, cache the details for later */
584 				bcopy(p->p_user.u_psargs, cache_psargs,
585 					sizeof (cache_psargs));
586 				cache_tp = tp;
587 				cache_t_state = tp->t_state;
588 				bailout = 1;
589 			}
590 			thread_unlock(tp);
591 		}
592 		mutex_exit(&pidlock);
593 
594 		/* were all the threads stopped? */
595 		if (!bailout)
596 			break;
597 	}
598 
599 	/* were we unable to stop all threads after a few tries? */
600 	if (bailout) {
601 		cmn_err(CE_NOTE, "process: %s id: %p state: %x\n",
602 			cache_psargs, cache_tp, cache_t_state);
603 
604 		(void) sprintf(sbdp_get_err_buf(sep), "%s", cache_psargs);
605 		sbdp_set_err(sep, ESGT_UTHREAD, NULL);
606 		return (ESRCH);
607 	}
608 
609 	return (DDI_SUCCESS);
610 }
611 
612 static void
613 sbdp_start_user_threads(void)
614 {
615 	kthread_id_t tp;
616 
617 	mutex_enter(&pidlock);
618 
619 	/* walk all threads and release them */
620 	for (tp = curthread->t_next; tp != curthread; tp = tp->t_next) {
621 		proc_t *p = ttoproc(tp);
622 
623 		/* skip kernel threads */
624 		if (ttoproc(tp)->p_as == &kas)
625 			continue;
626 
627 		mutex_enter(&p->p_lock);
628 		tp->t_proc_flag &= ~TP_CHKPT;
629 		mutex_exit(&p->p_lock);
630 
631 		thread_lock(tp);
632 		if (CPR_ISTOPPED(tp)) {
633 			/* back on the runq */
634 			tp->t_schedflag |= TS_RESUME;
635 			setrun_locked(tp);
636 		}
637 		thread_unlock(tp);
638 	}
639 
640 	mutex_exit(&pidlock);
641 }
642 
643 static void
644 sbdp_signal_user(int sig)
645 {
646 	struct proc *p;
647 
648 	mutex_enter(&pidlock);
649 
650 	for (p = practive; p != NULL; p = p->p_next) {
651 		/* only user threads */
652 		if (p->p_exec == NULL || p->p_stat == SZOMB ||
653 		    p == proc_init || p == ttoproc(curthread))
654 			continue;
655 
656 		mutex_enter(&p->p_lock);
657 		sigtoproc(p, NULL, sig);
658 		mutex_exit(&p->p_lock);
659 	}
660 
661 	mutex_exit(&pidlock);
662 
663 	/* add a bit of delay */
664 	delay(hz);
665 }
666 
667 static uint_t saved_watchdog_seconds;
668 
669 void
670 sbdp_resume(sbdp_sr_handle_t *srh)
671 {
672 	/*
673 	 * update the signature block
674 	 */
675 	CPU_SIGNATURE(OS_SIG, SIGST_RESUME_INPROGRESS, SIGSUBST_NULL,
676 	    CPU->cpu_id);
677 
678 	switch (SR_STATE(srh)) {
679 	case SBDP_SRSTATE_FULL:
680 
681 		ASSERT(MUTEX_HELD(&cpu_lock));
682 
683 		/*
684 		 * Prevent false alarm in tod_validate() due to tod
685 		 * value change between suspend and resume
686 		 */
687 		mutex_enter(&tod_lock);
688 		tod_fault_reset();
689 		mutex_exit(&tod_lock);
690 
691 		sbdp_enable_intr(); 	/* enable intr & clock */
692 
693 		/*
694 		 * release all the other cpus
695 		 * using start_cpus() vice sbdp_release_cpus()
696 		 */
697 		start_cpus();
698 		mutex_exit(&cpu_lock);
699 
700 		/*
701 		 * If we suspended hw watchdog at suspend,
702 		 * re-enable it now.
703 		 */
704 		if (SR_CHECK_FLAG(srh, SR_FLAG_WATCHDOG)) {
705 			mutex_enter(&tod_lock);
706 			tod_ops.tod_set_watchdog_timer(
707 				saved_watchdog_seconds);
708 			mutex_exit(&tod_lock);
709 		}
710 
711 		/* FALLTHROUGH */
712 
713 	case SBDP_SRSTATE_DRIVER:
714 		/*
715 		 * resume devices: root node doesn't have to
716 		 * be held in any way.
717 		 */
718 		sbdp_resume_devices(ddi_root_node(), srh);
719 
720 		/*
721 		 * resume the lock manager
722 		 */
723 		lm_cprresume();
724 
725 		/* FALLTHROUGH */
726 
727 	case SBDP_SRSTATE_USER:
728 		/*
729 		 * finally, resume user threads
730 		 */
731 		if (!sbdp_skip_user_threads) {
732 			SBDP_DBG_QR("DR: resuming user threads...\n");
733 			sbdp_start_user_threads();
734 		}
735 		/* FALLTHROUGH */
736 
737 	case SBDP_SRSTATE_BEGIN:
738 	default:
739 		/*
740 		 * let those who care know that we've just resumed
741 		 */
742 		SBDP_DBG_QR("sending SIGTHAW...\n");
743 		sbdp_signal_user(SIGTHAW);
744 		break;
745 	}
746 
747 	/*
748 	 * update the signature block
749 	 */
750 	CPU_SIGNATURE(OS_SIG, SIGST_RUN, SIGSUBST_NULL, CPU->cpu_id);
751 
752 	SBDP_DBG_QR("DR: resume COMPLETED\n");
753 }
754 
755 int
756 sbdp_suspend(sbdp_sr_handle_t *srh)
757 {
758 	int force;
759 	int rc = DDI_SUCCESS;
760 
761 	force = (srh && (srh->sr_flags & SBDP_IOCTL_FLAG_FORCE));
762 
763 	/*
764 	 * if no force flag, check for unsafe drivers
765 	 */
766 	if (force) {
767 		SBDP_DBG_QR("\nsbdp_suspend invoked with force flag");
768 	}
769 
770 	/*
771 	 * update the signature block
772 	 */
773 	CPU_SIGNATURE(OS_SIG, SIGST_QUIESCE_INPROGRESS, SIGSUBST_NULL,
774 	    CPU->cpu_id);
775 
776 	/*
777 	 * first, stop all user threads
778 	 */
779 	SBDP_DBG_QR("SBDP: suspending user threads...\n");
780 	SR_SET_STATE(srh, SBDP_SRSTATE_USER);
781 	if (((rc = sbdp_stop_user_threads(srh)) != DDI_SUCCESS) &&
782 	    sbdp_check_user_stop_result) {
783 		sbdp_resume(srh);
784 		return (rc);
785 	}
786 
787 #ifndef	SKIP_SYNC
788 	/*
789 	 * This sync swap out all user pages
790 	 */
791 	vfs_sync(SYNC_ALL);
792 #endif
793 
794 	/*
795 	 * special treatment for lock manager
796 	 */
797 	lm_cprsuspend();
798 
799 #ifndef	SKIP_SYNC
800 	/*
801 	 * sync the file system in case we never make it back
802 	 */
803 	sync();
804 
805 #endif
806 	/*
807 	 * now suspend drivers
808 	 */
809 	SBDP_DBG_QR("SBDP: suspending drivers...\n");
810 	SR_SET_STATE(srh, SBDP_SRSTATE_DRIVER);
811 
812 	/*
813 	 * Root node doesn't have to be held in any way.
814 	 */
815 	if ((rc = sbdp_suspend_devices(ddi_root_node(), srh)) != DDI_SUCCESS) {
816 		sbdp_resume(srh);
817 		return (rc);
818 	}
819 
820 	/*
821 	 * finally, grab all cpus
822 	 */
823 	SR_SET_STATE(srh, SBDP_SRSTATE_FULL);
824 
825 	/*
826 	 * if watchdog was activated, disable it
827 	 */
828 	if (watchdog_activated) {
829 		mutex_enter(&tod_lock);
830 		saved_watchdog_seconds = tod_ops.tod_clear_watchdog_timer();
831 		mutex_exit(&tod_lock);
832 		SR_SET_FLAG(srh, SR_FLAG_WATCHDOG);
833 	} else {
834 		SR_CLEAR_FLAG(srh, SR_FLAG_WATCHDOG);
835 	}
836 
837 	mutex_enter(&cpu_lock);
838 	pause_cpus(NULL);
839 	sbdp_stop_intr();
840 
841 	/*
842 	 * update the signature block
843 	 */
844 	CPU_SIGNATURE(OS_SIG, SIGST_QUIESCED, SIGSUBST_NULL, CPU->cpu_id);
845 
846 	return (rc);
847 }
848 
849 /*ARGSUSED*/
850 int
851 sbdp_test_suspend(sbdp_handle_t *hp)
852 {
853 	sbdp_sr_handle_t	*srh;
854 	int			err;
855 
856 	SBDP_DBG_QR("%s...\n", "sbdp_test_suspend");
857 
858 	srh = sbdp_get_sr_handle();
859 
860 	srh->sr_flags = hp->h_flags;
861 
862 	if ((err = sbdp_suspend(srh)) == DDI_SUCCESS) {
863 		sbdp_resume(srh);
864 	} else {
865 		SBDP_DBG_MISC("sbdp_suspend() failed, err = 0x%x\n", err);
866 	}
867 	sbdp_release_sr_handle(srh);
868 
869 	return (0);
870 }
871 
872 #ifdef	DEBUG
873 int
874 sbdp_passthru_test_quiesce(sbdp_handle_t *hp, void *arg)
875 {
876 	_NOTE(ARGUNUSED(arg))
877 
878 	return (sbdp_test_suspend(hp));
879 }
880 #endif
881