xref: /titanic_44/usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c (revision a4aeef46cda1835da2b19f8f62b4526de6521e6c)
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 2010 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 	int *refcount_non_gldv3;
238 	sbd_error_t *sep;
239 } sbdp_ref_t;
240 
241 static int
242 sbdp_check_dip(dev_info_t *dip, void *arg, uint_t ref)
243 {
244 	char		*dname;
245 	sbdp_ref_t	*sbrp = (sbdp_ref_t *)arg;
246 
247 	if (dip == NULL)
248 		return (DDI_WALK_CONTINUE);
249 
250 	ASSERT(sbrp->sep != NULL);
251 	ASSERT(sbrp->refcount != NULL);
252 
253 	if (!sbdp_is_real_device(dip))
254 		return (DDI_WALK_CONTINUE);
255 
256 	dname = ddi_binding_name(dip);
257 
258 	if ((strcmp(dname, "pciclass,060940") == 0) || (strcmp(dname,
259 	    "pciclass,060980") == 0)) {
260 		(void) ddi_pathname(dip, sbdp_get_err_buf(sbrp->sep));
261 		sbdp_set_err(sbrp->sep, ESBD_BUSY, NULL);
262 		(*sbrp->refcount)++;
263 		return (DDI_WALK_TERMINATE);
264 	}
265 
266 #ifdef DEBUG
267 	if (sbdp_bypass_device(dname))
268 		return (DDI_WALK_CONTINUE);
269 #endif
270 
271 	if (ref) {
272 		major_t	major;
273 
274 		(*sbrp->refcount)++;
275 		SBDP_DBG_QR("\n%s (major# %d) is referenced\n",
276 		    dname, ddi_name_to_major(dname));
277 		(void) ddi_pathname(dip, sbdp_get_err_buf(sbrp->sep));
278 		major = ddi_driver_major(dip);
279 		if (sbrp->refcount_non_gldv3 && NETWORK_PHYSDRV(major) &&
280 		    !GLDV3_DRV(major)) {
281 			(*sbrp->refcount_non_gldv3)++;
282 			return (DDI_WALK_CONTINUE);
283 		}
284 		sbdp_set_err(sbrp->sep, ESBD_BUSY, NULL);
285 		return (DDI_WALK_TERMINATE);
286 	}
287 	return (DDI_WALK_CONTINUE);
288 }
289 
290 void
291 sbdp_check_devices(dev_info_t *dip, int *refcount, sbd_error_t *sep,
292     int *refcount_non_gldv3)
293 {
294 	sbdp_ref_t sbr;
295 
296 	sbr.refcount = refcount;
297 	sbr.refcount_non_gldv3 = refcount_non_gldv3;
298 	sbr.sep = sep;
299 
300 	ASSERT(e_ddi_branch_held(dip));
301 
302 	(void) e_ddi_branch_referenced(dip, sbdp_check_dip, &sbr);
303 }
304 
305 /*
306  * Starting from the root node suspend all devices in the device tree.
307  * Assumes that all devices have already been marked busy.
308  */
309 static int
310 sbdp_suspend_devices_(dev_info_t *dip, sbdp_sr_handle_t *srh)
311 {
312 	major_t	major;
313 	char	*dname;
314 
315 	for (; dip != NULL; dip = ddi_get_next_sibling(dip)) {
316 		char	d_name[40], d_alias[40], *d_info;
317 
318 		if (sbdp_suspend_devices_(ddi_get_child(dip), srh)) {
319 			return (ENXIO);
320 		}
321 
322 		if (!sbdp_is_real_device(dip))
323 			continue;
324 
325 		major = (major_t)-1;
326 		if ((dname = DEVI(dip)->devi_binding_name) != NULL)
327 			major = ddi_name_to_major(dname);
328 
329 #ifdef DEBUG
330 		if (sbdp_bypass_device(dname)) {
331 			SBDP_DBG_QR("bypassed suspend of %s (major# %d)\n",
332 			    dname, major);
333 			continue;
334 		}
335 #endif
336 
337 		if ((d_info = ddi_get_name_addr(dip)) == NULL)
338 			d_info = "<null>";
339 
340 		d_name[0] = 0;
341 		if (sbdp_resolve_devname(dip, d_name, d_alias) == 0) {
342 			if (d_alias[0] != 0) {
343 				SBDP_DBG_QR("\tsuspending %s@%s (aka %s)\n",
344 				    d_name, d_info, d_alias);
345 			} else {
346 				SBDP_DBG_QR("\tsuspending %s@%s\n",
347 				    d_name, d_info);
348 			}
349 		} else {
350 			SBDP_DBG_QR("\tsuspending %s@%s\n", dname, d_info);
351 		}
352 
353 		if (devi_detach(dip, DDI_SUSPEND) != DDI_SUCCESS) {
354 			(void) sprintf(sbdp_get_err_buf(&srh->sep),
355 			    "%d", major);
356 
357 			sbdp_set_err(&srh->sep, ESGT_SUSPEND, NULL);
358 			ndi_hold_devi(dip);
359 			SR_FAILED_DIP(srh) = dip;
360 			return (DDI_FAILURE);
361 		}
362 	}
363 
364 	return (DDI_SUCCESS);
365 }
366 
367 /*ARGSUSED*/
368 static int
369 sbdp_suspend_devices_enter(dev_info_t *dip, void *arg)
370 {
371 	struct dev_info *devi = DEVI(dip);
372 	ndi_devi_enter(dip, &devi->devi_circular);
373 	return (DDI_WALK_CONTINUE);
374 }
375 
376 /*ARGSUSED*/
377 static int
378 sbdp_suspend_devices_exit(dev_info_t *dip, void *arg)
379 {
380 	struct dev_info *devi = DEVI(dip);
381 	ndi_devi_exit(dip, devi->devi_circular);
382 	return (DDI_WALK_CONTINUE);
383 }
384 
385 /*
386  * Before suspending devices first mark all device nodes busy. This
387  * avoids a deadlock situation when another thread holds a device busy
388  * and accesses an already suspended device.
389  */
390 static int
391 sbdp_suspend_devices(dev_info_t *dip, sbdp_sr_handle_t *srh)
392 {
393 	int	rv;
394 
395 	/* assumes dip is ddi_root_node so no ndi_devi_enter required */
396 	ASSERT(dip == ddi_root_node());
397 	ddi_walk_devs(dip, sbdp_suspend_devices_enter, NULL);
398 	rv = sbdp_suspend_devices_(dip, srh);
399 	ddi_walk_devs(dip, sbdp_suspend_devices_exit, NULL);
400 	return (rv);
401 }
402 
403 static void
404 sbdp_resume_devices(dev_info_t *start, sbdp_sr_handle_t *srh)
405 {
406 	int circ;
407 	dev_info_t	*dip, *next, *last = NULL;
408 	char		*bn;
409 	sbd_error_t	*sep;
410 
411 	sep = &srh->sep;
412 
413 	/* attach in reverse device tree order */
414 	while (last != start) {
415 		dip = start;
416 		next = ddi_get_next_sibling(dip);
417 		while (next != last && dip != SR_FAILED_DIP(srh)) {
418 			dip = next;
419 			next = ddi_get_next_sibling(dip);
420 		}
421 		if (dip == SR_FAILED_DIP(srh)) {
422 			/* Release hold acquired in sbdp_suspend_devices() */
423 			ndi_rele_devi(dip);
424 			SR_FAILED_DIP(srh) = NULL;
425 		} else if (sbdp_is_real_device(dip) &&
426 		    SR_FAILED_DIP(srh) == NULL) {
427 
428 			if (DEVI(dip)->devi_binding_name != NULL) {
429 				bn = ddi_binding_name(dip);
430 			}
431 #ifdef DEBUG
432 			if (!sbdp_bypass_device(bn)) {
433 #else
434 			{
435 #endif
436 				char	d_name[40], d_alias[40], *d_info;
437 
438 				d_name[0] = 0;
439 				d_info = ddi_get_name_addr(dip);
440 				if (d_info == NULL)
441 					d_info = "<null>";
442 
443 				if (!sbdp_resolve_devname(dip, d_name,
444 				    d_alias)) {
445 					if (d_alias[0] != 0) {
446 						SBDP_DBG_QR("\tresuming "
447 						    "%s@%s (aka %s)\n",
448 						    d_name, d_info,
449 						    d_alias);
450 					} else {
451 						SBDP_DBG_QR("\tresuming "
452 						    "%s@%s\n",
453 						    d_name, d_info);
454 					}
455 				} else {
456 					SBDP_DBG_QR("\tresuming %s@%s\n",
457 					    bn, d_info);
458 				}
459 
460 				if (devi_attach(dip, DDI_RESUME) !=
461 				    DDI_SUCCESS) {
462 					/*
463 					 * Print a console warning,
464 					 * set an errno of ESGT_RESUME,
465 					 * and save the driver major
466 					 * number in the e_str.
467 					 */
468 
469 					(void) sprintf(sbdp_get_err_buf(sep),
470 					    "%s@%s",
471 					    d_name[0] ? d_name : bn, d_info);
472 					SBDP_DBG_QR("\tFAILED to resume "
473 					    "%s\n", sbdp_get_err_buf(sep));
474 					sbdp_set_err(sep,
475 					    ESGT_RESUME, NULL);
476 				}
477 			}
478 		}
479 		ndi_devi_enter(dip, &circ);
480 		sbdp_resume_devices(ddi_get_child(dip), srh);
481 		ndi_devi_exit(dip, circ);
482 		last = dip;
483 	}
484 }
485 
486 /*
487  * True if thread is virtually stopped.  Similar to CPR_VSTOPPED
488  * but from DR point of view.  These user threads are waiting in
489  * the kernel.  Once they return from kernel, they will process
490  * the stop signal and stop.
491  */
492 #define	SBDP_VSTOPPED(t)			\
493 	((t)->t_state == TS_SLEEP &&		\
494 	(t)->t_wchan != NULL &&			\
495 	(t)->t_astflag &&		\
496 	((t)->t_proc_flag & TP_CHKPT))
497 
498 
499 static int
500 sbdp_stop_user_threads(sbdp_sr_handle_t *srh)
501 {
502 	int		count;
503 	char		cache_psargs[PSARGSZ];
504 	kthread_id_t	cache_tp;
505 	uint_t		cache_t_state;
506 	int		bailout;
507 	sbd_error_t	*sep;
508 	kthread_id_t 	tp;
509 
510 	extern void add_one_utstop();
511 	extern void utstop_timedwait(clock_t);
512 	extern void utstop_init(void);
513 
514 #define	SBDP_UTSTOP_RETRY	4
515 #define	SBDP_UTSTOP_WAIT	hz
516 
517 	if (sbdp_skip_user_threads)
518 		return (DDI_SUCCESS);
519 
520 	sep = &srh->sep;
521 	ASSERT(sep);
522 
523 	utstop_init();
524 
525 	/* we need to try a few times to get past fork, etc. */
526 	for (count = 0; count < SBDP_UTSTOP_RETRY; count++) {
527 		/* walk the entire threadlist */
528 		mutex_enter(&pidlock);
529 		for (tp = curthread->t_next; tp != curthread; tp = tp->t_next) {
530 			proc_t *p = ttoproc(tp);
531 
532 			/* handle kernel threads separately */
533 			if (p->p_as == &kas || p->p_stat == SZOMB)
534 				continue;
535 
536 			mutex_enter(&p->p_lock);
537 			thread_lock(tp);
538 
539 			if (tp->t_state == TS_STOPPED) {
540 				/* add another reason to stop this thread */
541 				tp->t_schedflag &= ~TS_RESUME;
542 			} else {
543 				tp->t_proc_flag |= TP_CHKPT;
544 
545 				thread_unlock(tp);
546 				mutex_exit(&p->p_lock);
547 				add_one_utstop();
548 				mutex_enter(&p->p_lock);
549 				thread_lock(tp);
550 
551 				aston(tp);
552 
553 				if (ISWAKEABLE(tp) || ISWAITING(tp)) {
554 					setrun_locked(tp);
555 				}
556 			}
557 
558 			/* grab thread if needed */
559 			if (tp->t_state == TS_ONPROC && tp->t_cpu != CPU)
560 				poke_cpu(tp->t_cpu->cpu_id);
561 
562 
563 			thread_unlock(tp);
564 			mutex_exit(&p->p_lock);
565 		}
566 		mutex_exit(&pidlock);
567 
568 
569 		/* let everything catch up */
570 		utstop_timedwait(count * count * SBDP_UTSTOP_WAIT);
571 
572 
573 		/* now, walk the threadlist again to see if we are done */
574 		mutex_enter(&pidlock);
575 		for (tp = curthread->t_next, bailout = 0;
576 		    tp != curthread; tp = tp->t_next) {
577 			proc_t *p = ttoproc(tp);
578 
579 			/* handle kernel threads separately */
580 			if (p->p_as == &kas || p->p_stat == SZOMB)
581 				continue;
582 
583 			/*
584 			 * If this thread didn't stop, and we don't allow
585 			 * unstopped blocked threads, bail.
586 			 */
587 			thread_lock(tp);
588 			if (!CPR_ISTOPPED(tp) &&
589 			    !(sbdp_allow_blocked_threads &&
590 			    SBDP_VSTOPPED(tp))) {
591 
592 				/* nope, cache the details for later */
593 				bcopy(p->p_user.u_psargs, cache_psargs,
594 				    sizeof (cache_psargs));
595 				cache_tp = tp;
596 				cache_t_state = tp->t_state;
597 				bailout = 1;
598 			}
599 			thread_unlock(tp);
600 		}
601 		mutex_exit(&pidlock);
602 
603 		/* were all the threads stopped? */
604 		if (!bailout)
605 			break;
606 	}
607 
608 	/* were we unable to stop all threads after a few tries? */
609 	if (bailout) {
610 		cmn_err(CE_NOTE, "process: %s id: %p state: %x\n",
611 		    cache_psargs, (void *)cache_tp, cache_t_state);
612 
613 		(void) sprintf(sbdp_get_err_buf(sep), "%s", cache_psargs);
614 		sbdp_set_err(sep, ESGT_UTHREAD, NULL);
615 		return (ESRCH);
616 	}
617 
618 	return (DDI_SUCCESS);
619 }
620 
621 static void
622 sbdp_start_user_threads(void)
623 {
624 	kthread_id_t tp;
625 
626 	mutex_enter(&pidlock);
627 
628 	/* walk all threads and release them */
629 	for (tp = curthread->t_next; tp != curthread; tp = tp->t_next) {
630 		proc_t *p = ttoproc(tp);
631 
632 		/* skip kernel threads */
633 		if (ttoproc(tp)->p_as == &kas)
634 			continue;
635 
636 		mutex_enter(&p->p_lock);
637 		tp->t_proc_flag &= ~TP_CHKPT;
638 		mutex_exit(&p->p_lock);
639 
640 		thread_lock(tp);
641 		if (CPR_ISTOPPED(tp)) {
642 			/* back on the runq */
643 			tp->t_schedflag |= TS_RESUME;
644 			setrun_locked(tp);
645 		}
646 		thread_unlock(tp);
647 	}
648 
649 	mutex_exit(&pidlock);
650 }
651 
652 static void
653 sbdp_signal_user(int sig)
654 {
655 	struct proc *p;
656 
657 	mutex_enter(&pidlock);
658 
659 	for (p = practive; p != NULL; p = p->p_next) {
660 		/* only user threads */
661 		if (p->p_exec == NULL || p->p_stat == SZOMB ||
662 		    p == proc_init || p == ttoproc(curthread))
663 			continue;
664 
665 		mutex_enter(&p->p_lock);
666 		sigtoproc(p, NULL, sig);
667 		mutex_exit(&p->p_lock);
668 	}
669 
670 	mutex_exit(&pidlock);
671 
672 	/* add a bit of delay */
673 	delay(hz);
674 }
675 
676 static uint_t saved_watchdog_seconds;
677 
678 void
679 sbdp_resume(sbdp_sr_handle_t *srh)
680 {
681 	/*
682 	 * update the signature block
683 	 */
684 	CPU_SIGNATURE(OS_SIG, SIGST_RESUME_INPROGRESS, SIGSUBST_NULL,
685 	    CPU->cpu_id);
686 
687 	switch (SR_STATE(srh)) {
688 	case SBDP_SRSTATE_FULL:
689 
690 		ASSERT(MUTEX_HELD(&cpu_lock));
691 
692 		/*
693 		 * Prevent false alarm in tod_validate() due to tod
694 		 * value change between suspend and resume
695 		 */
696 		mutex_enter(&tod_lock);
697 		tod_fault_reset();
698 		mutex_exit(&tod_lock);
699 
700 		sbdp_enable_intr(); 	/* enable intr & clock */
701 
702 		/*
703 		 * release all the other cpus
704 		 * using start_cpus() vice sbdp_release_cpus()
705 		 */
706 		start_cpus();
707 		mutex_exit(&cpu_lock);
708 
709 		/*
710 		 * If we suspended hw watchdog at suspend,
711 		 * re-enable it now.
712 		 */
713 		if (SR_CHECK_FLAG(srh, SR_FLAG_WATCHDOG)) {
714 			mutex_enter(&tod_lock);
715 			tod_ops.tod_set_watchdog_timer(
716 			    saved_watchdog_seconds);
717 			mutex_exit(&tod_lock);
718 		}
719 
720 		/* FALLTHROUGH */
721 
722 	case SBDP_SRSTATE_DRIVER:
723 		/*
724 		 * resume devices: root node doesn't have to
725 		 * be held in any way.
726 		 */
727 		sbdp_resume_devices(ddi_root_node(), srh);
728 
729 		/*
730 		 * resume the lock manager
731 		 */
732 		lm_cprresume();
733 
734 		/* FALLTHROUGH */
735 
736 	case SBDP_SRSTATE_USER:
737 		/*
738 		 * finally, resume user threads
739 		 */
740 		if (!sbdp_skip_user_threads) {
741 			SBDP_DBG_QR("DR: resuming user threads...\n");
742 			sbdp_start_user_threads();
743 		}
744 		/* FALLTHROUGH */
745 
746 	case SBDP_SRSTATE_BEGIN:
747 	default:
748 		/*
749 		 * let those who care know that we've just resumed
750 		 */
751 		SBDP_DBG_QR("sending SIGTHAW...\n");
752 		sbdp_signal_user(SIGTHAW);
753 		break;
754 	}
755 
756 	/*
757 	 * update the signature block
758 	 */
759 	CPU_SIGNATURE(OS_SIG, SIGST_RUN, SIGSUBST_NULL, CPU->cpu_id);
760 
761 	SBDP_DBG_QR("DR: resume COMPLETED\n");
762 }
763 
764 int
765 sbdp_suspend(sbdp_sr_handle_t *srh)
766 {
767 	int force;
768 	int rc = DDI_SUCCESS;
769 
770 	force = (srh && (srh->sr_flags & SBDP_IOCTL_FLAG_FORCE));
771 
772 	/*
773 	 * if no force flag, check for unsafe drivers
774 	 */
775 	if (force) {
776 		SBDP_DBG_QR("\nsbdp_suspend invoked with force flag");
777 	}
778 
779 	/*
780 	 * update the signature block
781 	 */
782 	CPU_SIGNATURE(OS_SIG, SIGST_QUIESCE_INPROGRESS, SIGSUBST_NULL,
783 	    CPU->cpu_id);
784 
785 	/*
786 	 * first, stop all user threads
787 	 */
788 	SBDP_DBG_QR("SBDP: suspending user threads...\n");
789 	SR_SET_STATE(srh, SBDP_SRSTATE_USER);
790 	if (((rc = sbdp_stop_user_threads(srh)) != DDI_SUCCESS) &&
791 	    sbdp_check_user_stop_result) {
792 		sbdp_resume(srh);
793 		return (rc);
794 	}
795 
796 #ifndef	SKIP_SYNC
797 	/*
798 	 * This sync swap out all user pages
799 	 */
800 	vfs_sync(SYNC_ALL);
801 #endif
802 
803 	/*
804 	 * special treatment for lock manager
805 	 */
806 	lm_cprsuspend();
807 
808 #ifndef	SKIP_SYNC
809 	/*
810 	 * sync the file system in case we never make it back
811 	 */
812 	sync();
813 
814 #endif
815 	/*
816 	 * now suspend drivers
817 	 */
818 	SBDP_DBG_QR("SBDP: suspending drivers...\n");
819 	SR_SET_STATE(srh, SBDP_SRSTATE_DRIVER);
820 
821 	/*
822 	 * Root node doesn't have to be held in any way.
823 	 */
824 	if ((rc = sbdp_suspend_devices(ddi_root_node(), srh)) != DDI_SUCCESS) {
825 		sbdp_resume(srh);
826 		return (rc);
827 	}
828 
829 	/*
830 	 * finally, grab all cpus
831 	 */
832 	SR_SET_STATE(srh, SBDP_SRSTATE_FULL);
833 
834 	/*
835 	 * if watchdog was activated, disable it
836 	 */
837 	if (watchdog_activated) {
838 		mutex_enter(&tod_lock);
839 		saved_watchdog_seconds = tod_ops.tod_clear_watchdog_timer();
840 		mutex_exit(&tod_lock);
841 		SR_SET_FLAG(srh, SR_FLAG_WATCHDOG);
842 	} else {
843 		SR_CLEAR_FLAG(srh, SR_FLAG_WATCHDOG);
844 	}
845 
846 	mutex_enter(&cpu_lock);
847 	pause_cpus(NULL);
848 	sbdp_stop_intr();
849 
850 	/*
851 	 * update the signature block
852 	 */
853 	CPU_SIGNATURE(OS_SIG, SIGST_QUIESCED, SIGSUBST_NULL, CPU->cpu_id);
854 
855 	return (rc);
856 }
857 
858 /*ARGSUSED*/
859 int
860 sbdp_test_suspend(sbdp_handle_t *hp)
861 {
862 	sbdp_sr_handle_t	*srh;
863 	int			err;
864 
865 	SBDP_DBG_QR("%s...\n", "sbdp_test_suspend");
866 
867 	srh = sbdp_get_sr_handle();
868 
869 	srh->sr_flags = hp->h_flags;
870 
871 	if ((err = sbdp_suspend(srh)) == DDI_SUCCESS) {
872 		sbdp_resume(srh);
873 	} else {
874 		SBDP_DBG_MISC("sbdp_suspend() failed, err = 0x%x\n", err);
875 	}
876 	sbdp_release_sr_handle(srh);
877 
878 	return (0);
879 }
880 
881 #ifdef	DEBUG
882 int
883 sbdp_passthru_test_quiesce(sbdp_handle_t *hp, void *arg)
884 {
885 	_NOTE(ARGUNUSED(arg))
886 
887 	return (sbdp_test_suspend(hp));
888 }
889 #endif
890