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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 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 starfire/starcat 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 #include <sys/cpu_sgnblk_defs.h> 59 #include <sys/dr.h> 60 #include <sys/dr_util.h> 61 62 #include <sys/promif.h> 63 #include <sys/conf.h> 64 #include <sys/cyclic.h> 65 66 extern void e_ddi_enter_driver_list(struct devnames *dnp, int *listcnt); 67 extern void e_ddi_exit_driver_list(struct devnames *dnp, int listcnt); 68 extern int is_pseudo_device(dev_info_t *dip); 69 70 extern kmutex_t cpu_lock; 71 extern dr_unsafe_devs_t dr_unsafe_devs; 72 73 static int dr_is_real_device(dev_info_t *dip); 74 static int dr_is_unsafe_major(major_t major); 75 static int dr_bypass_device(char *dname); 76 static int dr_check_dip(dev_info_t *dip, void *arg, uint_t ref); 77 static int dr_resolve_devname(dev_info_t *dip, char *buffer, 78 char *alias); 79 static sbd_error_t *drerr_int(int e_code, uint64_t *arr, int idx, 80 int majors); 81 static int dr_add_int(uint64_t *arr, int idx, int len, 82 uint64_t val); 83 84 int dr_pt_test_suspend(dr_handle_t *hp); 85 86 /* 87 * dr_quiesce.c interface 88 * NOTE: states used internally by dr_suspend and dr_resume 89 */ 90 typedef enum dr_suspend_state { 91 DR_SRSTATE_BEGIN = 0, 92 DR_SRSTATE_USER, 93 DR_SRSTATE_DRIVER, 94 DR_SRSTATE_FULL 95 } suspend_state_t; 96 97 struct dr_sr_handle { 98 dr_handle_t *sr_dr_handlep; 99 dev_info_t *sr_failed_dip; 100 suspend_state_t sr_suspend_state; 101 uint_t sr_flags; 102 uint64_t sr_err_ints[DR_MAX_ERR_INT]; 103 int sr_err_idx; 104 }; 105 106 #define SR_FLAG_WATCHDOG 0x1 107 108 /* 109 * XXX 110 * This hack will go away before RTI. Just for testing. 111 * List of drivers to bypass when performing a suspend. 112 */ 113 static char *dr_bypass_list[] = { 114 "" 115 }; 116 117 118 #define SKIP_SYNC /* bypass sync ops in dr_suspend */ 119 120 /* 121 * dr_skip_user_threads is used to control if user threads should 122 * be suspended. If dr_skip_user_threads is true, the rest of the 123 * flags are not used; if it is false, dr_check_user_stop_result 124 * will be used to control whether or not we need to check suspend 125 * result, and dr_allow_blocked_threads will be used to control 126 * whether or not we allow suspend to continue if there are blocked 127 * threads. We allow all combinations of dr_check_user_stop_result 128 * and dr_allow_block_threads, even though it might not make much 129 * sense to not allow block threads when we don't even check stop 130 * result. 131 */ 132 static int dr_skip_user_threads = 0; /* default to FALSE */ 133 static int dr_check_user_stop_result = 1; /* default to TRUE */ 134 static int dr_allow_blocked_threads = 1; /* default to TRUE */ 135 136 #define DR_CPU_LOOP_MSEC 1000 137 138 static void 139 dr_stop_intr(void) 140 { 141 ASSERT(MUTEX_HELD(&cpu_lock)); 142 143 kpreempt_disable(); 144 cyclic_suspend(); 145 } 146 147 static void 148 dr_enable_intr(void) 149 { 150 ASSERT(MUTEX_HELD(&cpu_lock)); 151 152 cyclic_resume(); 153 kpreempt_enable(); 154 } 155 156 dr_sr_handle_t * 157 dr_get_sr_handle(dr_handle_t *hp) 158 { 159 dr_sr_handle_t *srh; 160 161 srh = GETSTRUCT(dr_sr_handle_t, 1); 162 srh->sr_dr_handlep = hp; 163 164 return (srh); 165 } 166 167 void 168 dr_release_sr_handle(dr_sr_handle_t *srh) 169 { 170 ASSERT(srh->sr_failed_dip == NULL); 171 FREESTRUCT(srh, dr_sr_handle_t, 1); 172 } 173 174 static int 175 dr_is_real_device(dev_info_t *dip) 176 { 177 struct regspec *regbuf = NULL; 178 int length = 0; 179 int rc; 180 181 if (ddi_get_driver(dip) == NULL) 182 return (0); 183 184 if (DEVI(dip)->devi_pm_flags & (PMC_NEEDS_SR|PMC_PARENTAL_SR)) 185 return (1); 186 if (DEVI(dip)->devi_pm_flags & PMC_NO_SR) 187 return (0); 188 189 /* 190 * now the general case 191 */ 192 rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg", 193 (caddr_t)®buf, &length); 194 ASSERT(rc != DDI_PROP_NO_MEMORY); 195 if (rc != DDI_PROP_SUCCESS) { 196 return (0); 197 } else { 198 if ((length > 0) && (regbuf != NULL)) 199 kmem_free(regbuf, length); 200 return (1); 201 } 202 } 203 204 static int 205 dr_is_unsafe_major(major_t major) 206 { 207 char *dname, **cpp; 208 int i, ndevs; 209 210 if ((dname = ddi_major_to_name(major)) == NULL) { 211 PR_QR("dr_is_unsafe_major: invalid major # %d\n", major); 212 return (0); 213 } 214 215 ndevs = dr_unsafe_devs.ndevs; 216 for (i = 0, cpp = dr_unsafe_devs.devnames; i < ndevs; i++) { 217 if (strcmp(dname, *cpp++) == 0) 218 return (1); 219 } 220 return (0); 221 } 222 223 static int 224 dr_bypass_device(char *dname) 225 { 226 int i; 227 char **lname; 228 /* check the bypass list */ 229 for (i = 0, lname = &dr_bypass_list[i]; **lname != '\0'; lname++) { 230 if (strcmp(dname, dr_bypass_list[i++]) == 0) 231 return (1); 232 } 233 return (0); 234 } 235 236 static int 237 dr_resolve_devname(dev_info_t *dip, char *buffer, char *alias) 238 { 239 major_t devmajor; 240 char *aka, *name; 241 242 *buffer = *alias = 0; 243 244 if (dip == NULL) 245 return (-1); 246 247 if ((name = ddi_get_name(dip)) == NULL) 248 name = "<null name>"; 249 250 aka = name; 251 252 if ((devmajor = ddi_name_to_major(aka)) != -1) 253 aka = ddi_major_to_name(devmajor); 254 255 strcpy(buffer, name); 256 257 if (strcmp(name, aka)) 258 strcpy(alias, aka); 259 else 260 *alias = 0; 261 262 return (0); 263 } 264 265 struct dr_ref { 266 int *refcount; 267 uint64_t *arr; 268 int *idx; 269 int len; 270 }; 271 272 /* ARGSUSED */ 273 static int 274 dr_check_dip(dev_info_t *dip, void *arg, uint_t ref) 275 { 276 major_t major; 277 char *dname; 278 struct dr_ref *rp = (struct dr_ref *)arg; 279 280 if (dip == NULL) 281 return (DDI_WALK_CONTINUE); 282 283 if (!dr_is_real_device(dip)) 284 return (DDI_WALK_CONTINUE); 285 286 dname = ddi_binding_name(dip); 287 288 if (dr_bypass_device(dname)) 289 return (DDI_WALK_CONTINUE); 290 291 if (dname && ((major = ddi_name_to_major(dname)) != (major_t)-1)) { 292 if (ref && rp->refcount) { 293 *rp->refcount += ref; 294 PR_QR("\n %s (major# %d) is referenced(%u)\n", 295 dname, major, ref); 296 } 297 if (dr_is_unsafe_major(major) && 298 i_ddi_node_state(dip) >= DS_ATTACHED) { 299 PR_QR("\n %s (major# %d) not hotpluggable\n", 300 dname, major); 301 if (rp->arr != NULL && rp->idx != NULL) 302 *rp->idx = dr_add_int(rp->arr, *rp->idx, 303 rp->len, (uint64_t)major); 304 } 305 } 306 return (DDI_WALK_CONTINUE); 307 } 308 309 static int 310 dr_check_unsafe_major(dev_info_t *dip, void *arg) 311 { 312 return (dr_check_dip(dip, arg, 0)); 313 } 314 315 316 /*ARGSUSED*/ 317 void 318 dr_check_devices(dev_info_t *dip, int *refcount, dr_handle_t *handle, 319 uint64_t *arr, int *idx, int len) 320 { 321 struct dr_ref bref = {0}; 322 323 if (dip == NULL) 324 return; 325 326 bref.refcount = refcount; 327 bref.arr = arr; 328 bref.idx = idx; 329 bref.len = len; 330 331 ASSERT(e_ddi_branch_held(dip)); 332 (void) e_ddi_branch_referenced(dip, dr_check_dip, &bref); 333 } 334 335 /* 336 * The "dip" argument's parent (if it exists) must be held busy. 337 */ 338 static int 339 dr_suspend_devices(dev_info_t *dip, dr_sr_handle_t *srh) 340 { 341 dr_handle_t *handle; 342 major_t major; 343 char *dname; 344 int circ; 345 346 /* 347 * If dip is the root node, it has no siblings and it is 348 * always held. If dip is not the root node, dr_suspend_devices() 349 * will be invoked with the parent held busy. 350 */ 351 for (; dip != NULL; dip = ddi_get_next_sibling(dip)) { 352 char d_name[40], d_alias[40], *d_info; 353 354 ndi_devi_enter(dip, &circ); 355 if (dr_suspend_devices(ddi_get_child(dip), srh)) { 356 ndi_devi_exit(dip, circ); 357 return (ENXIO); 358 } 359 ndi_devi_exit(dip, circ); 360 361 if (!dr_is_real_device(dip)) 362 continue; 363 364 major = (major_t)-1; 365 if ((dname = ddi_binding_name(dip)) != NULL) 366 major = ddi_name_to_major(dname); 367 368 if (dr_bypass_device(dname)) { 369 PR_QR(" bypassed suspend of %s (major# %d)\n", dname, 370 major); 371 continue; 372 } 373 374 if (drmach_verify_sr(dip, 1)) { 375 PR_QR(" bypassed suspend of %s (major# %d)\n", dname, 376 major); 377 continue; 378 } 379 380 if ((d_info = ddi_get_name_addr(dip)) == NULL) 381 d_info = "<null>"; 382 383 d_name[0] = 0; 384 if (dr_resolve_devname(dip, d_name, d_alias) == 0) { 385 if (d_alias[0] != 0) { 386 prom_printf("\tsuspending %s@%s (aka %s)\n", 387 d_name, d_info, d_alias); 388 } else { 389 prom_printf("\tsuspending %s@%s\n", 390 d_name, d_info); 391 } 392 } else { 393 prom_printf("\tsuspending %s@%s\n", dname, d_info); 394 } 395 396 if (devi_detach(dip, DDI_SUSPEND) != DDI_SUCCESS) { 397 prom_printf("\tFAILED to suspend %s@%s\n", 398 d_name[0] ? d_name : dname, d_info); 399 400 srh->sr_err_idx = dr_add_int(srh->sr_err_ints, 401 srh->sr_err_idx, DR_MAX_ERR_INT, 402 (uint64_t)major); 403 404 ndi_hold_devi(dip); 405 srh->sr_failed_dip = dip; 406 407 handle = srh->sr_dr_handlep; 408 dr_op_err(CE_IGNORE, handle, ESBD_SUSPEND, "%s@%s", 409 d_name[0] ? d_name : dname, d_info); 410 411 return (DDI_FAILURE); 412 } 413 } 414 415 return (DDI_SUCCESS); 416 } 417 418 static void 419 dr_resume_devices(dev_info_t *start, dr_sr_handle_t *srh) 420 { 421 dr_handle_t *handle; 422 dev_info_t *dip, *next, *last = NULL; 423 major_t major; 424 char *bn; 425 int circ; 426 427 major = (major_t)-1; 428 429 /* attach in reverse device tree order */ 430 while (last != start) { 431 dip = start; 432 next = ddi_get_next_sibling(dip); 433 while (next != last && dip != srh->sr_failed_dip) { 434 dip = next; 435 next = ddi_get_next_sibling(dip); 436 } 437 if (dip == srh->sr_failed_dip) { 438 /* release hold acquired in dr_suspend_devices() */ 439 srh->sr_failed_dip = NULL; 440 ndi_rele_devi(dip); 441 } else if (dr_is_real_device(dip) && 442 srh->sr_failed_dip == NULL) { 443 444 if ((bn = ddi_binding_name(dip)) != NULL) { 445 major = ddi_name_to_major(bn); 446 } else { 447 bn = "<null>"; 448 } 449 if (!dr_bypass_device(bn) && 450 !drmach_verify_sr(dip, 0)) { 451 char d_name[40], d_alias[40], *d_info; 452 453 d_name[0] = 0; 454 d_info = ddi_get_name_addr(dip); 455 if (d_info == NULL) 456 d_info = "<null>"; 457 458 if (!dr_resolve_devname(dip, d_name, 459 d_alias)) { 460 if (d_alias[0] != 0) { 461 prom_printf("\tresuming " 462 "%s@%s (aka %s)\n", 463 d_name, d_info, 464 d_alias); 465 } else { 466 prom_printf("\tresuming " 467 "%s@%s\n", 468 d_name, d_info); 469 } 470 } else { 471 prom_printf("\tresuming %s@%s\n", 472 bn, d_info); 473 } 474 475 if (devi_attach(dip, DDI_RESUME) != 476 DDI_SUCCESS) { 477 /* 478 * Print a console warning, 479 * set an e_code of ESBD_RESUME, 480 * and save the driver major 481 * number in the e_rsc. 482 */ 483 prom_printf("\tFAILED to resume %s@%s", 484 d_name[0] ? d_name : bn, d_info); 485 486 srh->sr_err_idx = 487 dr_add_int(srh->sr_err_ints, 488 srh->sr_err_idx, DR_MAX_ERR_INT, 489 (uint64_t)major); 490 491 handle = srh->sr_dr_handlep; 492 493 dr_op_err(CE_IGNORE, handle, 494 ESBD_RESUME, "%s@%s", 495 d_name[0] ? d_name : bn, d_info); 496 } 497 } 498 } 499 500 /* Hold parent busy while walking its children */ 501 ndi_devi_enter(dip, &circ); 502 dr_resume_devices(ddi_get_child(dip), srh); 503 ndi_devi_exit(dip, circ); 504 last = dip; 505 } 506 } 507 508 /* 509 * True if thread is virtually stopped. Similar to CPR_VSTOPPED 510 * but from DR point of view. These user threads are waiting in 511 * the kernel. Once they complete in the kernel, they will process 512 * the stop signal and stop. 513 */ 514 #define DR_VSTOPPED(t) \ 515 ((t)->t_state == TS_SLEEP && \ 516 (t)->t_wchan != NULL && \ 517 (t)->t_astflag && \ 518 ((t)->t_proc_flag & TP_CHKPT)) 519 520 /* ARGSUSED */ 521 static int 522 dr_stop_user_threads(dr_sr_handle_t *srh) 523 { 524 int count; 525 int bailout; 526 dr_handle_t *handle = srh->sr_dr_handlep; 527 static fn_t f = "dr_stop_user_threads"; 528 kthread_id_t tp; 529 530 extern void add_one_utstop(); 531 extern void utstop_timedwait(clock_t); 532 extern void utstop_init(void); 533 534 #define DR_UTSTOP_RETRY 4 535 #define DR_UTSTOP_WAIT hz 536 537 if (dr_skip_user_threads) 538 return (DDI_SUCCESS); 539 540 utstop_init(); 541 542 /* we need to try a few times to get past fork, etc. */ 543 srh->sr_err_idx = 0; 544 for (count = 0; count < DR_UTSTOP_RETRY; count++) { 545 /* walk the entire threadlist */ 546 mutex_enter(&pidlock); 547 for (tp = curthread->t_next; tp != curthread; tp = tp->t_next) { 548 proc_t *p = ttoproc(tp); 549 550 /* handle kernel threads separately */ 551 if (p->p_as == &kas || p->p_stat == SZOMB) 552 continue; 553 554 mutex_enter(&p->p_lock); 555 thread_lock(tp); 556 557 if (tp->t_state == TS_STOPPED) { 558 /* add another reason to stop this thread */ 559 tp->t_schedflag &= ~TS_RESUME; 560 } else { 561 tp->t_proc_flag |= TP_CHKPT; 562 563 thread_unlock(tp); 564 mutex_exit(&p->p_lock); 565 add_one_utstop(); 566 mutex_enter(&p->p_lock); 567 thread_lock(tp); 568 569 aston(tp); 570 571 if (tp->t_state == TS_SLEEP && 572 (tp->t_flag & T_WAKEABLE)) { 573 setrun_locked(tp); 574 } 575 576 } 577 578 /* grab thread if needed */ 579 if (tp->t_state == TS_ONPROC && tp->t_cpu != CPU) 580 poke_cpu(tp->t_cpu->cpu_id); 581 582 583 thread_unlock(tp); 584 mutex_exit(&p->p_lock); 585 } 586 mutex_exit(&pidlock); 587 588 589 /* let everything catch up */ 590 utstop_timedwait(count * count * DR_UTSTOP_WAIT); 591 592 593 /* now, walk the threadlist again to see if we are done */ 594 mutex_enter(&pidlock); 595 for (tp = curthread->t_next, bailout = 0; 596 tp != curthread; tp = tp->t_next) { 597 proc_t *p = ttoproc(tp); 598 599 /* handle kernel threads separately */ 600 if (p->p_as == &kas || p->p_stat == SZOMB) 601 continue; 602 603 /* 604 * If this thread didn't stop, and we don't allow 605 * unstopped blocked threads, bail. 606 */ 607 thread_lock(tp); 608 if (!CPR_ISTOPPED(tp) && 609 !(dr_allow_blocked_threads && 610 DR_VSTOPPED(tp))) { 611 bailout = 1; 612 if (count == DR_UTSTOP_RETRY - 1) { 613 /* 614 * save the pid for later reporting 615 */ 616 srh->sr_err_idx = 617 dr_add_int(srh->sr_err_ints, 618 srh->sr_err_idx, DR_MAX_ERR_INT, 619 (uint64_t)p->p_pid); 620 621 cmn_err(CE_WARN, "%s: " 622 "failed to stop thread: " 623 "process=%s, pid=%d", 624 f, p->p_user.u_psargs, p->p_pid); 625 626 PR_QR("%s: failed to stop thread: " 627 "process=%s, pid=%d, t_id=0x%p, " 628 "t_state=0x%x, t_proc_flag=0x%x, " 629 "t_schedflag=0x%x\n", 630 f, p->p_user.u_psargs, p->p_pid, 631 tp, tp->t_state, tp->t_proc_flag, 632 tp->t_schedflag); 633 } 634 635 } 636 thread_unlock(tp); 637 } 638 mutex_exit(&pidlock); 639 640 /* were all the threads stopped? */ 641 if (!bailout) 642 break; 643 } 644 645 /* were we unable to stop all threads after a few tries? */ 646 if (bailout) { 647 handle->h_err = drerr_int(ESBD_UTHREAD, srh->sr_err_ints, 648 srh->sr_err_idx, 0); 649 return (ESRCH); 650 } 651 652 return (DDI_SUCCESS); 653 } 654 655 static void 656 dr_start_user_threads(void) 657 { 658 kthread_id_t tp; 659 660 mutex_enter(&pidlock); 661 662 /* walk all threads and release them */ 663 for (tp = curthread->t_next; tp != curthread; tp = tp->t_next) { 664 proc_t *p = ttoproc(tp); 665 666 /* skip kernel threads */ 667 if (ttoproc(tp)->p_as == &kas) 668 continue; 669 670 mutex_enter(&p->p_lock); 671 tp->t_proc_flag &= ~TP_CHKPT; 672 mutex_exit(&p->p_lock); 673 674 thread_lock(tp); 675 if (CPR_ISTOPPED(tp)) { 676 /* back on the runq */ 677 tp->t_schedflag |= TS_RESUME; 678 setrun_locked(tp); 679 } 680 thread_unlock(tp); 681 } 682 683 mutex_exit(&pidlock); 684 } 685 686 static void 687 dr_signal_user(int sig) 688 { 689 struct proc *p; 690 691 mutex_enter(&pidlock); 692 693 for (p = practive; p != NULL; p = p->p_next) { 694 /* only user threads */ 695 if (p->p_exec == NULL || p->p_stat == SZOMB || 696 p == proc_init || p == ttoproc(curthread)) 697 continue; 698 699 mutex_enter(&p->p_lock); 700 sigtoproc(p, NULL, sig); 701 mutex_exit(&p->p_lock); 702 } 703 704 mutex_exit(&pidlock); 705 706 /* add a bit of delay */ 707 delay(hz); 708 } 709 710 void 711 dr_resume(dr_sr_handle_t *srh) 712 { 713 dr_handle_t *handle; 714 715 handle = srh->sr_dr_handlep; 716 717 if (srh->sr_suspend_state < DR_SRSTATE_FULL) { 718 /* 719 * Update the signature block. 720 * If cpus are not paused, this can be done now. 721 * See comments below. 722 */ 723 CPU_SIGNATURE(OS_SIG, SIGST_RESUME_INPROGRESS, SIGSUBST_NULL, 724 CPU->cpu_id); 725 } 726 727 switch (srh->sr_suspend_state) { 728 case DR_SRSTATE_FULL: 729 730 ASSERT(MUTEX_HELD(&cpu_lock)); 731 732 dr_enable_intr(); /* enable intr & clock */ 733 734 start_cpus(); 735 mutex_exit(&cpu_lock); 736 737 /* 738 * Update the signature block. 739 * This must not be done while cpus are paused, since on 740 * Starcat the cpu signature update aquires an adaptive 741 * mutex in the iosram driver. Blocking with cpus paused 742 * can lead to deadlock. 743 */ 744 CPU_SIGNATURE(OS_SIG, SIGST_RESUME_INPROGRESS, SIGSUBST_NULL, 745 CPU->cpu_id); 746 747 /* 748 * If we suspended hw watchdog at suspend, 749 * re-enable it now. 750 */ 751 752 if (srh->sr_flags & (SR_FLAG_WATCHDOG)) { 753 mutex_enter(&tod_lock); 754 tod_ops.tod_set_watchdog_timer( 755 watchdog_timeout_seconds); 756 mutex_exit(&tod_lock); 757 } 758 759 /* 760 * This should only be called if drmach_suspend_last() 761 * was called and state transitioned to DR_SRSTATE_FULL 762 * to prevent resume attempts on device instances that 763 * were not previously suspended. 764 */ 765 drmach_resume_first(); 766 767 /* FALLTHROUGH */ 768 769 case DR_SRSTATE_DRIVER: 770 /* 771 * resume drivers 772 */ 773 srh->sr_err_idx = 0; 774 775 /* no parent dip to hold busy */ 776 dr_resume_devices(ddi_root_node(), srh); 777 778 if (srh->sr_err_idx && srh->sr_dr_handlep) { 779 (srh->sr_dr_handlep)->h_err = drerr_int(ESBD_RESUME, 780 srh->sr_err_ints, srh->sr_err_idx, 1); 781 } 782 783 /* 784 * resume the lock manager 785 */ 786 lm_cprresume(); 787 788 /* FALLTHROUGH */ 789 790 case DR_SRSTATE_USER: 791 /* 792 * finally, resume user threads 793 */ 794 if (!dr_skip_user_threads) { 795 prom_printf("DR: resuming user threads...\n"); 796 dr_start_user_threads(); 797 } 798 /* FALLTHROUGH */ 799 800 case DR_SRSTATE_BEGIN: 801 default: 802 /* 803 * let those who care know that we've just resumed 804 */ 805 PR_QR("sending SIGTHAW...\n"); 806 dr_signal_user(SIGTHAW); 807 break; 808 } 809 810 i_ndi_allow_device_tree_changes(handle->h_ndi); 811 812 /* 813 * update the signature block 814 */ 815 CPU_SIGNATURE(OS_SIG, SIGST_RUN, SIGSUBST_NULL, CPU->cpu_id); 816 817 prom_printf("DR: resume COMPLETED\n"); 818 } 819 820 int 821 dr_suspend(dr_sr_handle_t *srh) 822 { 823 dr_handle_t *handle; 824 int force; 825 int dev_errs_idx; 826 uint64_t dev_errs[DR_MAX_ERR_INT]; 827 int rc = DDI_SUCCESS; 828 829 handle = srh->sr_dr_handlep; 830 831 force = dr_cmd_flags(handle) & SBD_FLAG_FORCE; 832 833 /* 834 * update the signature block 835 */ 836 CPU_SIGNATURE(OS_SIG, SIGST_QUIESCE_INPROGRESS, SIGSUBST_NULL, 837 CPU->cpu_id); 838 839 i_ndi_block_device_tree_changes(&handle->h_ndi); 840 841 prom_printf("\nDR: suspending user threads...\n"); 842 srh->sr_suspend_state = DR_SRSTATE_USER; 843 if (((rc = dr_stop_user_threads(srh)) != DDI_SUCCESS) && 844 dr_check_user_stop_result) { 845 dr_resume(srh); 846 return (rc); 847 } 848 849 if (!force) { 850 struct dr_ref drc = {0}; 851 852 prom_printf("\nDR: checking devices...\n"); 853 dev_errs_idx = 0; 854 855 drc.arr = dev_errs; 856 drc.idx = &dev_errs_idx; 857 drc.len = DR_MAX_ERR_INT; 858 859 /* 860 * Since the root node can never go away, it 861 * doesn't have to be held. 862 */ 863 ddi_walk_devs(ddi_root_node(), dr_check_unsafe_major, &drc); 864 if (dev_errs_idx) { 865 handle->h_err = drerr_int(ESBD_UNSAFE, dev_errs, 866 dev_errs_idx, 1); 867 dr_resume(srh); 868 return (DDI_FAILURE); 869 } 870 PR_QR("done\n"); 871 } else { 872 prom_printf("\nDR: dr_suspend invoked with force flag\n"); 873 } 874 875 #ifndef SKIP_SYNC 876 /* 877 * This sync swap out all user pages 878 */ 879 vfs_sync(SYNC_ALL); 880 #endif 881 882 /* 883 * special treatment for lock manager 884 */ 885 lm_cprsuspend(); 886 887 #ifndef SKIP_SYNC 888 /* 889 * sync the file system in case we never make it back 890 */ 891 sync(); 892 #endif 893 894 /* 895 * now suspend drivers 896 */ 897 prom_printf("DR: suspending drivers...\n"); 898 srh->sr_suspend_state = DR_SRSTATE_DRIVER; 899 srh->sr_err_idx = 0; 900 /* No parent to hold busy */ 901 if ((rc = dr_suspend_devices(ddi_root_node(), srh)) != DDI_SUCCESS) { 902 if (srh->sr_err_idx && srh->sr_dr_handlep) { 903 (srh->sr_dr_handlep)->h_err = drerr_int(ESBD_SUSPEND, 904 srh->sr_err_ints, srh->sr_err_idx, 1); 905 } 906 dr_resume(srh); 907 return (rc); 908 } 909 910 drmach_suspend_last(); 911 912 /* 913 * finally, grab all cpus 914 */ 915 srh->sr_suspend_state = DR_SRSTATE_FULL; 916 917 /* 918 * if watchdog was activated, disable it 919 */ 920 if (watchdog_activated) { 921 mutex_enter(&tod_lock); 922 tod_ops.tod_clear_watchdog_timer(); 923 mutex_exit(&tod_lock); 924 srh->sr_flags |= SR_FLAG_WATCHDOG; 925 } else { 926 srh->sr_flags &= ~(SR_FLAG_WATCHDOG); 927 } 928 929 /* 930 * Update the signature block. 931 * This must be done before cpus are paused, since on Starcat the 932 * cpu signature update aquires an adaptive mutex in the iosram driver. 933 * Blocking with cpus paused can lead to deadlock. 934 */ 935 CPU_SIGNATURE(OS_SIG, SIGST_QUIESCED, SIGSUBST_NULL, CPU->cpu_id); 936 937 mutex_enter(&cpu_lock); 938 pause_cpus(NULL); 939 dr_stop_intr(); 940 941 return (rc); 942 } 943 944 int 945 dr_pt_test_suspend(dr_handle_t *hp) 946 { 947 dr_sr_handle_t *srh; 948 int err; 949 uint_t psmerr; 950 static fn_t f = "dr_pt_test_suspend"; 951 952 PR_QR("%s...\n", f); 953 954 srh = dr_get_sr_handle(hp); 955 if ((err = dr_suspend(srh)) == DDI_SUCCESS) { 956 dr_resume(srh); 957 if ((hp->h_err) && ((psmerr = hp->h_err->e_code) != 0)) { 958 PR_QR("%s: error on dr_resume()", f); 959 switch (psmerr) { 960 case ESBD_RESUME: 961 PR_QR("Couldn't resume devices: %s\n", 962 DR_GET_E_RSC(hp->h_err)); 963 break; 964 965 case ESBD_KTHREAD: 966 PR_ALL("psmerr is ESBD_KTHREAD\n"); 967 break; 968 default: 969 PR_ALL("Resume error unknown = %d\n", 970 psmerr); 971 break; 972 } 973 } 974 } else { 975 PR_ALL("%s: dr_suspend() failed, err = 0x%x\n", 976 f, err); 977 psmerr = hp->h_err ? hp->h_err->e_code : ESBD_NOERROR; 978 switch (psmerr) { 979 case ESBD_UNSAFE: 980 PR_ALL("Unsafe devices (major #): %s\n", 981 DR_GET_E_RSC(hp->h_err)); 982 break; 983 984 case ESBD_RTTHREAD: 985 PR_ALL("RT threads (PIDs): %s\n", 986 DR_GET_E_RSC(hp->h_err)); 987 break; 988 989 case ESBD_UTHREAD: 990 PR_ALL("User threads (PIDs): %s\n", 991 DR_GET_E_RSC(hp->h_err)); 992 break; 993 994 case ESBD_SUSPEND: 995 PR_ALL("Non-suspendable devices (major #): %s\n", 996 DR_GET_E_RSC(hp->h_err)); 997 break; 998 999 case ESBD_RESUME: 1000 PR_ALL("Could not resume devices (major #): %s\n", 1001 DR_GET_E_RSC(hp->h_err)); 1002 break; 1003 1004 case ESBD_KTHREAD: 1005 PR_ALL("psmerr is ESBD_KTHREAD\n"); 1006 break; 1007 1008 case ESBD_NOERROR: 1009 PR_ALL("sbd_error_t error code not set\n"); 1010 break; 1011 1012 default: 1013 PR_ALL("Unknown error psmerr = %d\n", psmerr); 1014 break; 1015 } 1016 } 1017 dr_release_sr_handle(srh); 1018 1019 return (0); 1020 } 1021 1022 /* 1023 * Add a new integer value to the end of an array. Don't allow duplicates to 1024 * appear in the array, and don't allow the array to overflow. Return the new 1025 * total number of entries in the array. 1026 */ 1027 static int 1028 dr_add_int(uint64_t *arr, int idx, int len, uint64_t val) 1029 { 1030 int i; 1031 1032 if (arr == NULL) 1033 return (0); 1034 1035 if (idx >= len) 1036 return (idx); 1037 1038 for (i = 0; i < idx; i++) { 1039 if (arr[i] == val) 1040 return (idx); 1041 } 1042 1043 arr[idx++] = val; 1044 1045 return (idx); 1046 } 1047 1048 /* 1049 * Construct an sbd_error_t featuring a string representation of an array of 1050 * integers as its e_rsc. 1051 */ 1052 static sbd_error_t * 1053 drerr_int(int e_code, uint64_t *arr, int idx, int majors) 1054 { 1055 int i, n, buf_len, buf_idx, buf_avail; 1056 char *dname; 1057 char *buf; 1058 sbd_error_t *new_sbd_err; 1059 static char s_ellipsis[] = "..."; 1060 1061 if (arr == NULL || idx <= 0) 1062 return (NULL); 1063 1064 /* MAXPATHLEN is the size of the e_rsc field in sbd_error_t. */ 1065 buf = (char *)kmem_zalloc(MAXPATHLEN, KM_SLEEP); 1066 1067 /* 1068 * This is the total working area of the buffer. It must be computed 1069 * as the size of 'buf', minus reserved space for the null terminator 1070 * and the ellipsis string. 1071 */ 1072 buf_len = MAXPATHLEN - (strlen(s_ellipsis) + 1); 1073 1074 /* Construct a string representation of the array values */ 1075 for (buf_idx = 0, i = 0; i < idx; i++) { 1076 buf_avail = buf_len - buf_idx; 1077 if (majors) { 1078 dname = ddi_major_to_name(arr[i]); 1079 if (dname) { 1080 n = snprintf(&buf[buf_idx], buf_avail, 1081 "%s, ", dname); 1082 } else { 1083 n = snprintf(&buf[buf_idx], buf_avail, 1084 "major %lu, ", arr[i]); 1085 } 1086 } else { 1087 n = snprintf(&buf[buf_idx], buf_avail, "%lu, ", 1088 arr[i]); 1089 } 1090 1091 /* An ellipsis gets appended when no more values fit */ 1092 if (n >= buf_avail) { 1093 (void) strcpy(&buf[buf_idx], s_ellipsis); 1094 break; 1095 } 1096 1097 buf_idx += n; 1098 } 1099 1100 /* If all the contents fit, remove the trailing comma */ 1101 if (n < buf_avail) { 1102 buf[--buf_idx] = '\0'; 1103 buf[--buf_idx] = '\0'; 1104 } 1105 1106 /* Return an sbd_error_t with the buffer and e_code */ 1107 new_sbd_err = drerr_new(1, e_code, buf); 1108 kmem_free(buf, MAXPATHLEN); 1109 return (new_sbd_err); 1110 } 1111