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