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)®buf, &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