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