1 /* $OpenBSD: subr_autoconf.c,v 1.92 2016/03/14 23:08:06 krw Exp $ */ 2 /* $NetBSD: subr_autoconf.c,v 1.21 1996/04/04 06:06:18 cgd Exp $ */ 3 4 /* 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This software was developed by the Computer Systems Engineering group 9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 10 * contributed to Berkeley. 11 * 12 * All advertising materials mentioning features or use of this software 13 * must display the following acknowledgement: 14 * This product includes software developed by the University of 15 * California, Lawrence Berkeley Laboratories. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 3. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp (LBL) 42 * 43 * @(#)subr_autoconf.c 8.1 (Berkeley) 6/10/93 44 */ 45 46 #include <sys/param.h> 47 #include <sys/device.h> 48 #include <sys/hotplug.h> 49 #include <sys/malloc.h> 50 #include <sys/systm.h> 51 #include <sys/queue.h> 52 #include <sys/mutex.h> 53 #include <sys/atomic.h> 54 55 #include "hotplug.h" 56 #include "mpath.h" 57 58 /* 59 * Autoconfiguration subroutines. 60 */ 61 62 /* 63 * ioconf.c exports exactly two names: cfdata and cfroots. All system 64 * devices and drivers are found via these tables. 65 */ 66 extern short cfroots[]; 67 68 #define ROOT ((struct device *)NULL) 69 70 struct matchinfo { 71 cfmatch_t fn; 72 struct device *parent; 73 void *match, *aux; 74 int indirect, pri; 75 }; 76 77 #ifndef AUTOCONF_VERBOSE 78 #define AUTOCONF_VERBOSE 0 79 #endif /* AUTOCONF_VERBOSE */ 80 int autoconf_verbose = AUTOCONF_VERBOSE; /* trace probe calls */ 81 82 static void mapply(struct matchinfo *, struct cfdata *); 83 84 struct deferred_config { 85 TAILQ_ENTRY(deferred_config) dc_queue; 86 struct device *dc_dev; 87 void (*dc_func)(struct device *); 88 }; 89 90 TAILQ_HEAD(, deferred_config) deferred_config_queue; 91 TAILQ_HEAD(, deferred_config) mountroot_config_queue; 92 93 void *config_rootsearch(cfmatch_t, char *, void *); 94 void config_process_deferred_children(struct device *); 95 96 struct devicelist alldevs; /* list of all devices */ 97 98 volatile int config_pending; /* semaphore for mountroot */ 99 100 struct mutex autoconf_attdet_mtx = MUTEX_INITIALIZER(IPL_HIGH); 101 /* 102 * If > 0, devices are being attached and any thread which tries to 103 * detach will sleep; if < 0 devices are being detached and any 104 * thread which tries to attach will sleep. 105 */ 106 int autoconf_attdet; 107 108 /* 109 * Initialize autoconfiguration data structures. This occurs before console 110 * initialization as that might require use of this subsystem. Furthermore 111 * this means that malloc et al. isn't yet available. 112 */ 113 void 114 config_init(void) 115 { 116 TAILQ_INIT(&deferred_config_queue); 117 TAILQ_INIT(&mountroot_config_queue); 118 TAILQ_INIT(&alldevs); 119 } 120 121 /* 122 * Apply the matching function and choose the best. This is used 123 * a few times and we want to keep the code small. 124 */ 125 void 126 mapply(struct matchinfo *m, struct cfdata *cf) 127 { 128 int pri; 129 void *match; 130 131 if (m->indirect) 132 match = config_make_softc(m->parent, cf); 133 else 134 match = cf; 135 136 if (autoconf_verbose) { 137 printf(">>> probing for %s", cf->cf_driver->cd_name); 138 if (cf->cf_fstate == FSTATE_STAR) 139 printf("*\n"); 140 else 141 printf("%d\n", cf->cf_unit); 142 } 143 if (m->fn != NULL) 144 pri = (*m->fn)(m->parent, match, m->aux); 145 else { 146 if (cf->cf_attach->ca_match == NULL) { 147 panic("mapply: no match function for '%s' device", 148 cf->cf_driver->cd_name); 149 } 150 pri = (*cf->cf_attach->ca_match)(m->parent, match, m->aux); 151 } 152 if (autoconf_verbose) 153 printf(">>> %s probe returned %d\n", cf->cf_driver->cd_name, 154 pri); 155 156 if (pri > m->pri) { 157 if (m->indirect && m->match) 158 free(m->match, M_DEVBUF, 0); 159 m->match = match; 160 m->pri = pri; 161 } else { 162 if (m->indirect) 163 free(match, M_DEVBUF, 0); 164 } 165 } 166 167 /* 168 * Iterate over all potential children of some device, calling the given 169 * function (default being the child's match function) for each one. 170 * Nonzero returns are matches; the highest value returned is considered 171 * the best match. Return the `found child' if we got a match, or NULL 172 * otherwise. The `aux' pointer is simply passed on through. 173 * 174 * Note that this function is designed so that it can be used to apply 175 * an arbitrary function to all potential children (its return value 176 * can be ignored). 177 */ 178 void * 179 config_search(cfmatch_t fn, struct device *parent, void *aux) 180 { 181 struct cfdata *cf; 182 short *p; 183 struct matchinfo m; 184 185 m.fn = fn; 186 m.parent = parent; 187 m.match = NULL; 188 m.aux = aux; 189 m.indirect = parent && parent->dv_cfdata->cf_driver->cd_indirect; 190 m.pri = 0; 191 192 for (cf = cfdata; cf->cf_driver; cf++) { 193 /* 194 * Skip cf if no longer eligible, otherwise scan 195 * through parents for one matching `parent', 196 * and try match function. 197 */ 198 if (cf->cf_fstate == FSTATE_FOUND) 199 continue; 200 if (cf->cf_fstate == FSTATE_DNOTFOUND || 201 cf->cf_fstate == FSTATE_DSTAR) 202 continue; 203 for (p = cf->cf_parents; *p >= 0; p++) 204 if (parent->dv_cfdata == &cfdata[*p]) 205 mapply(&m, cf); 206 } 207 208 if (autoconf_verbose) { 209 if (m.match) { 210 if (m.indirect) 211 cf = ((struct device *)m.match)->dv_cfdata; 212 else 213 cf = (struct cfdata *)m.match; 214 printf(">>> %s probe won\n", 215 cf->cf_driver->cd_name); 216 } else 217 printf(">>> no winning probe\n"); 218 } 219 return (m.match); 220 } 221 222 /* 223 * Iterate over all potential children of some device, calling the given 224 * function for each one. 225 * 226 * Note that this function is designed so that it can be used to apply 227 * an arbitrary function to all potential children (its return value 228 * can be ignored). 229 */ 230 void 231 config_scan(cfscan_t fn, struct device *parent) 232 { 233 struct cfdata *cf; 234 short *p; 235 void *match; 236 int indirect; 237 238 indirect = parent && parent->dv_cfdata->cf_driver->cd_indirect; 239 240 for (cf = cfdata; cf->cf_driver; cf++) { 241 /* 242 * Skip cf if no longer eligible, otherwise scan 243 * through parents for one matching `parent', 244 * and try match function. 245 */ 246 if (cf->cf_fstate == FSTATE_FOUND) 247 continue; 248 if (cf->cf_fstate == FSTATE_DNOTFOUND || 249 cf->cf_fstate == FSTATE_DSTAR) 250 continue; 251 for (p = cf->cf_parents; *p >= 0; p++) 252 if (parent->dv_cfdata == &cfdata[*p]) { 253 match = indirect? 254 config_make_softc(parent, cf) : 255 (void *)cf; 256 (*fn)(parent, match); 257 } 258 } 259 } 260 261 /* 262 * Find the given root device. 263 * This is much like config_search, but there is no parent. 264 */ 265 void * 266 config_rootsearch(cfmatch_t fn, char *rootname, void *aux) 267 { 268 struct cfdata *cf; 269 short *p; 270 struct matchinfo m; 271 272 m.fn = fn; 273 m.parent = ROOT; 274 m.match = NULL; 275 m.aux = aux; 276 m.indirect = 0; 277 m.pri = 0; 278 /* 279 * Look at root entries for matching name. We do not bother 280 * with found-state here since only one instance of each possible 281 * root child should ever be searched. 282 */ 283 for (p = cfroots; *p >= 0; p++) { 284 cf = &cfdata[*p]; 285 if (cf->cf_fstate == FSTATE_DNOTFOUND || 286 cf->cf_fstate == FSTATE_DSTAR) 287 continue; 288 if (strcmp(cf->cf_driver->cd_name, rootname) == 0) 289 mapply(&m, cf); 290 } 291 return (m.match); 292 } 293 294 const char *msgs[3] = { "", " not configured\n", " unsupported\n" }; 295 296 /* 297 * The given `aux' argument describes a device that has been found 298 * on the given parent, but not necessarily configured. Locate the 299 * configuration data for that device (using the submatch function 300 * provided, or using candidates' cd_match configuration driver 301 * functions) and attach it, and return true. If the device was 302 * not configured, call the given `print' function and return 0. 303 */ 304 struct device * 305 config_found_sm(struct device *parent, void *aux, cfprint_t print, 306 cfmatch_t submatch) 307 { 308 void *match; 309 310 if ((match = config_search(submatch, parent, aux)) != NULL) 311 return (config_attach(parent, match, aux, print)); 312 if (print) 313 printf("%s", msgs[(*print)(aux, parent->dv_xname)]); 314 return (NULL); 315 } 316 317 /* 318 * As above, but for root devices. 319 */ 320 struct device * 321 config_rootfound(char *rootname, void *aux) 322 { 323 void *match; 324 325 if ((match = config_rootsearch((cfmatch_t)NULL, rootname, aux)) != NULL) 326 return (config_attach(ROOT, match, aux, (cfprint_t)NULL)); 327 printf("root device %s not configured\n", rootname); 328 return (NULL); 329 } 330 331 /* 332 * Attach a found device. Allocates memory for device variables. 333 */ 334 struct device * 335 config_attach(struct device *parent, void *match, void *aux, cfprint_t print) 336 { 337 struct cfdata *cf; 338 struct device *dev; 339 struct cfdriver *cd; 340 struct cfattach *ca; 341 342 mtx_enter(&autoconf_attdet_mtx); 343 while (autoconf_attdet < 0) 344 msleep(&autoconf_attdet, &autoconf_attdet_mtx, 345 PWAIT, "autoconf", 0); 346 autoconf_attdet++; 347 mtx_leave(&autoconf_attdet_mtx); 348 349 if (parent && parent->dv_cfdata->cf_driver->cd_indirect) { 350 dev = match; 351 cf = dev->dv_cfdata; 352 } else { 353 cf = match; 354 dev = config_make_softc(parent, cf); 355 } 356 357 cd = cf->cf_driver; 358 ca = cf->cf_attach; 359 360 KASSERT(cd->cd_devs != NULL); 361 KASSERT(dev->dv_unit < cd->cd_ndevs); 362 KASSERT(cd->cd_devs[dev->dv_unit] == NULL); 363 cd->cd_devs[dev->dv_unit] = dev; 364 365 /* 366 * If this is a "STAR" device and we used the last unit, prepare for 367 * another one. 368 */ 369 if (cf->cf_fstate == FSTATE_STAR) { 370 if (dev->dv_unit == cf->cf_unit) 371 cf->cf_unit++; 372 } else 373 cf->cf_fstate = FSTATE_FOUND; 374 375 TAILQ_INSERT_TAIL(&alldevs, dev, dv_list); 376 device_ref(dev); 377 378 if (parent == ROOT) 379 printf("%s at root", dev->dv_xname); 380 else { 381 printf("%s at %s", dev->dv_xname, parent->dv_xname); 382 if (print) 383 (void) (*print)(aux, NULL); 384 } 385 386 /* 387 * Before attaching, clobber any unfound devices that are 388 * otherwise identical, or bump the unit number on all starred 389 * cfdata for this device. 390 */ 391 for (cf = cfdata; cf->cf_driver; cf++) { 392 if (cf->cf_driver == cd && 393 cf->cf_unit == dev->dv_unit) { 394 if (cf->cf_fstate == FSTATE_NOTFOUND) 395 cf->cf_fstate = FSTATE_FOUND; 396 if (cf->cf_fstate == FSTATE_STAR) 397 cf->cf_unit++; 398 } 399 } 400 device_register(dev, aux); 401 (*ca->ca_attach)(parent, dev, aux); 402 config_process_deferred_children(dev); 403 #if NHOTPLUG > 0 404 if (!cold) 405 hotplug_device_attach(cd->cd_class, dev->dv_xname); 406 #endif 407 408 mtx_enter(&autoconf_attdet_mtx); 409 if (--autoconf_attdet == 0) 410 wakeup(&autoconf_attdet); 411 mtx_leave(&autoconf_attdet_mtx); 412 return (dev); 413 } 414 415 struct device * 416 config_make_softc(struct device *parent, struct cfdata *cf) 417 { 418 struct device *dev; 419 struct cfdriver *cd; 420 struct cfattach *ca; 421 422 cd = cf->cf_driver; 423 ca = cf->cf_attach; 424 if (ca->ca_devsize < sizeof(struct device)) 425 panic("config_make_softc"); 426 427 /* get memory for all device vars */ 428 dev = malloc(ca->ca_devsize, M_DEVBUF, M_NOWAIT|M_ZERO); 429 if (dev == NULL) 430 panic("config_make_softc: allocation for device softc failed"); 431 432 dev->dv_class = cd->cd_class; 433 dev->dv_cfdata = cf; 434 dev->dv_flags = DVF_ACTIVE; /* always initially active */ 435 436 /* If this is a STAR device, search for a free unit number */ 437 if (cf->cf_fstate == FSTATE_STAR) { 438 for (dev->dv_unit = cf->cf_starunit1; 439 dev->dv_unit < cf->cf_unit; dev->dv_unit++) 440 if (cd->cd_ndevs == 0 || 441 dev->dv_unit >= cd->cd_ndevs || 442 cd->cd_devs[dev->dv_unit] == NULL) 443 break; 444 } else 445 dev->dv_unit = cf->cf_unit; 446 447 /* Build the device name into dv_xname. */ 448 if (snprintf(dev->dv_xname, sizeof(dev->dv_xname), "%s%d", 449 cd->cd_name, dev->dv_unit) >= sizeof(dev->dv_xname)) 450 panic("config_make_softc: device name too long"); 451 dev->dv_parent = parent; 452 453 /* put this device in the devices array */ 454 if (dev->dv_unit >= cd->cd_ndevs) { 455 /* 456 * Need to expand the array. 457 */ 458 int old = cd->cd_ndevs, new; 459 void **nsp; 460 461 if (old == 0) 462 new = MINALLOCSIZE / sizeof(void *); 463 else 464 new = old * 2; 465 while (new <= dev->dv_unit) 466 new *= 2; 467 cd->cd_ndevs = new; 468 nsp = mallocarray(new, sizeof(void *), M_DEVBUF, M_NOWAIT|M_ZERO); 469 if (nsp == NULL) 470 panic("config_make_softc: %sing dev array", 471 old != 0 ? "expand" : "creat"); 472 if (old != 0) { 473 bcopy(cd->cd_devs, nsp, old * sizeof(void *)); 474 free(cd->cd_devs, M_DEVBUF, 0); 475 } 476 cd->cd_devs = nsp; 477 } 478 if (cd->cd_devs[dev->dv_unit]) 479 panic("config_make_softc: duplicate %s", dev->dv_xname); 480 481 dev->dv_ref = 1; 482 483 return (dev); 484 } 485 486 /* 487 * Detach a device. Optionally forced (e.g. because of hardware 488 * removal) and quiet. Returns zero if successful, non-zero 489 * (an error code) otherwise. 490 * 491 * Note that this code wants to be run from a process context, so 492 * that the detach can sleep to allow processes which have a device 493 * open to run and unwind their stacks. 494 */ 495 int 496 config_detach(struct device *dev, int flags) 497 { 498 struct cfdata *cf; 499 struct cfattach *ca; 500 struct cfdriver *cd; 501 int rv = 0, i; 502 #ifdef DIAGNOSTIC 503 struct device *d; 504 #endif 505 #if NHOTPLUG > 0 506 char devname[16]; 507 #endif 508 509 mtx_enter(&autoconf_attdet_mtx); 510 while (autoconf_attdet > 0) 511 msleep(&autoconf_attdet, &autoconf_attdet_mtx, 512 PWAIT, "autoconf", 0); 513 autoconf_attdet--; 514 mtx_leave(&autoconf_attdet_mtx); 515 516 #if NHOTPLUG > 0 517 strlcpy(devname, dev->dv_xname, sizeof(devname)); 518 #endif 519 520 cf = dev->dv_cfdata; 521 #ifdef DIAGNOSTIC 522 if (cf->cf_fstate != FSTATE_FOUND && cf->cf_fstate != FSTATE_STAR) 523 panic("config_detach: bad device fstate"); 524 #endif 525 ca = cf->cf_attach; 526 cd = cf->cf_driver; 527 528 /* 529 * Ensure the device is deactivated. If the device has an 530 * activation entry point and DVF_ACTIVE is still set, the 531 * device is busy, and the detach fails. 532 */ 533 rv = config_deactivate(dev); 534 535 /* 536 * Try to detach the device. If that's not possible, then 537 * we either panic() (for the forced but failed case), or 538 * return an error. 539 */ 540 if (rv == 0) { 541 if (ca->ca_detach != NULL) 542 rv = (*ca->ca_detach)(dev, flags); 543 else 544 rv = EOPNOTSUPP; 545 } 546 if (rv != 0) { 547 if ((flags & DETACH_FORCE) == 0) 548 goto done; 549 else 550 panic("config_detach: forced detach of %s failed (%d)", 551 dev->dv_xname, rv); 552 } 553 554 /* 555 * The device has now been successfully detached. 556 */ 557 558 #ifdef DIAGNOSTIC 559 /* 560 * Sanity: If you're successfully detached, you should have no 561 * children. (Note that because children must be attached 562 * after parents, we only need to search the latter part of 563 * the list.) 564 */ 565 i = 0; 566 for (d = TAILQ_NEXT(dev, dv_list); d != NULL; 567 d = TAILQ_NEXT(d, dv_list)) { 568 if (d->dv_parent == dev) { 569 printf("config_detach: %s attached at %s\n", 570 d->dv_xname, dev->dv_xname); 571 i = 1; 572 } 573 } 574 if (i != 0) 575 panic("config_detach: detached device (%s) has children", 576 dev->dv_xname); 577 #endif 578 579 /* 580 * Mark cfdata to show that the unit can be reused, if possible. 581 * Note that we can only re-use a starred unit number if the unit 582 * being detached had the last assigned unit number. 583 */ 584 for (cf = cfdata; cf->cf_driver; cf++) { 585 if (cf->cf_driver == cd) { 586 if (cf->cf_fstate == FSTATE_FOUND && 587 cf->cf_unit == dev->dv_unit) 588 cf->cf_fstate = FSTATE_NOTFOUND; 589 if (cf->cf_fstate == FSTATE_STAR && 590 cf->cf_unit == dev->dv_unit + 1) 591 cf->cf_unit--; 592 } 593 } 594 595 /* 596 * Unlink from device list. 597 */ 598 TAILQ_REMOVE(&alldevs, dev, dv_list); 599 device_unref(dev); 600 601 /* 602 * Remove from cfdriver's array, tell the world, and free softc. 603 */ 604 cd->cd_devs[dev->dv_unit] = NULL; 605 if ((flags & DETACH_QUIET) == 0) 606 printf("%s detached\n", dev->dv_xname); 607 608 device_unref(dev); 609 /* 610 * If the device now has no units in use, deallocate its softc array. 611 */ 612 for (i = 0; i < cd->cd_ndevs; i++) 613 if (cd->cd_devs[i] != NULL) 614 break; 615 if (i == cd->cd_ndevs) { /* nothing found; deallocate */ 616 free(cd->cd_devs, M_DEVBUF, 0); 617 cd->cd_devs = NULL; 618 cd->cd_ndevs = 0; 619 cf->cf_unit = 0; 620 } 621 622 #if NHOTPLUG > 0 623 if (!cold) 624 hotplug_device_detach(cd->cd_class, devname); 625 #endif 626 627 /* 628 * Return success. 629 */ 630 done: 631 mtx_enter(&autoconf_attdet_mtx); 632 if (++autoconf_attdet == 0) 633 wakeup(&autoconf_attdet); 634 mtx_leave(&autoconf_attdet_mtx); 635 return (rv); 636 } 637 638 int 639 config_deactivate(struct device *dev) 640 { 641 int rv = 0, oflags = dev->dv_flags; 642 643 if (dev->dv_flags & DVF_ACTIVE) { 644 dev->dv_flags &= ~DVF_ACTIVE; 645 rv = config_suspend(dev, DVACT_DEACTIVATE); 646 if (rv) 647 dev->dv_flags = oflags; 648 } 649 return (rv); 650 } 651 652 /* 653 * Defer the configuration of the specified device until all 654 * of its parent's devices have been attached. 655 */ 656 void 657 config_defer(struct device *dev, void (*func)(struct device *)) 658 { 659 struct deferred_config *dc; 660 661 if (dev->dv_parent == NULL) 662 panic("config_defer: can't defer config of a root device"); 663 664 #ifdef DIAGNOSTIC 665 for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL; 666 dc = TAILQ_NEXT(dc, dc_queue)) { 667 if (dc->dc_dev == dev) 668 panic("config_defer: deferred twice"); 669 } 670 #endif 671 672 if ((dc = malloc(sizeof(*dc), M_DEVBUF, M_NOWAIT)) == NULL) 673 panic("config_defer: can't allocate defer structure"); 674 675 dc->dc_dev = dev; 676 dc->dc_func = func; 677 TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue); 678 config_pending_incr(); 679 } 680 681 /* 682 * Defer the configuration of the specified device until after 683 * root file system is mounted. 684 */ 685 void 686 config_mountroot(struct device *dev, void (*func)(struct device *)) 687 { 688 struct deferred_config *dc; 689 690 /* 691 * No need to defer if root file system is already mounted. 692 */ 693 if (rootvp != NULL) { 694 (*func)(dev); 695 return; 696 } 697 698 #ifdef DIAGNOSTIC 699 for (dc = TAILQ_FIRST(&mountroot_config_queue); dc != NULL; 700 dc = TAILQ_NEXT(dc, dc_queue)) { 701 if (dc->dc_dev == dev) 702 panic("config_mountroot: deferred twice"); 703 } 704 #endif 705 706 if ((dc = malloc(sizeof(*dc), M_DEVBUF, M_NOWAIT)) == NULL) 707 panic("config_mountroot: can't allocate defer structure"); 708 709 dc->dc_dev = dev; 710 dc->dc_func = func; 711 TAILQ_INSERT_TAIL(&mountroot_config_queue, dc, dc_queue); 712 } 713 714 /* 715 * Process the deferred configuration queue for a device. 716 */ 717 void 718 config_process_deferred_children(struct device *parent) 719 { 720 struct deferred_config *dc, *ndc; 721 722 for (dc = TAILQ_FIRST(&deferred_config_queue); 723 dc != NULL; dc = ndc) { 724 ndc = TAILQ_NEXT(dc, dc_queue); 725 if (dc->dc_dev->dv_parent == parent) { 726 TAILQ_REMOVE(&deferred_config_queue, dc, dc_queue); 727 (*dc->dc_func)(dc->dc_dev); 728 free(dc, M_DEVBUF, sizeof(*dc)); 729 config_pending_decr(); 730 } 731 } 732 } 733 734 /* 735 * Process the deferred configuration queue after the root file 736 * system is mounted . 737 */ 738 void 739 config_process_deferred_mountroot(void) 740 { 741 struct deferred_config *dc; 742 743 while ((dc = TAILQ_FIRST(&mountroot_config_queue)) != NULL) { 744 TAILQ_REMOVE(&mountroot_config_queue, dc, dc_queue); 745 (*dc->dc_func)(dc->dc_dev); 746 free(dc, M_DEVBUF, sizeof(*dc)); 747 } 748 } 749 750 /* 751 * Manipulate the config_pending semaphore. 752 */ 753 void 754 config_pending_incr(void) 755 { 756 757 config_pending++; 758 } 759 760 void 761 config_pending_decr(void) 762 { 763 764 #ifdef DIAGNOSTIC 765 if (config_pending == 0) 766 panic("config_pending_decr: config_pending == 0"); 767 #endif 768 config_pending--; 769 if (config_pending == 0) 770 wakeup((void *)&config_pending); 771 } 772 773 int 774 config_detach_children(struct device *parent, int flags) 775 { 776 struct device *dev, *next_dev; 777 int rv = 0; 778 779 /* 780 * The config_detach routine may sleep, meaning devices 781 * may be added to the queue. However, all devices will 782 * be added to the tail of the queue, the queue won't 783 * be re-organized, and the subtree of parent here should be locked 784 * for purposes of adding/removing children. 785 * 786 * Note that we can not afford trying to walk the device list 787 * once - our ``next'' device might be a child of the device 788 * we are about to detach, so it would disappear. 789 * Just play it safe and restart from the parent. 790 */ 791 for (dev = TAILQ_LAST(&alldevs, devicelist); 792 dev != NULL; dev = next_dev) { 793 if (dev->dv_parent == parent) { 794 if ((rv = config_detach(dev, flags)) != 0) 795 return (rv); 796 next_dev = TAILQ_LAST(&alldevs, devicelist); 797 } else { 798 next_dev = TAILQ_PREV(dev, devicelist, dv_list); 799 } 800 } 801 802 return (0); 803 } 804 805 int 806 config_suspend(struct device *dev, int act) 807 { 808 struct cfattach *ca = dev->dv_cfdata->cf_attach; 809 int r; 810 811 device_ref(dev); 812 if (ca->ca_activate) 813 r = (*ca->ca_activate)(dev, act); 814 else 815 r = config_activate_children(dev, act); 816 device_unref(dev); 817 return (r); 818 } 819 820 int 821 config_suspend_all(int act) 822 { 823 struct device *mainbus = device_mainbus(); 824 struct device *mpath = device_mpath(); 825 int rv = 0; 826 827 switch (act) { 828 case DVACT_QUIESCE: 829 case DVACT_SUSPEND: 830 case DVACT_POWERDOWN: 831 if (mpath) { 832 rv = config_suspend(mpath, act); 833 if (rv) 834 return rv; 835 } 836 if (mainbus) 837 rv = config_suspend(mainbus, act); 838 break; 839 case DVACT_RESUME: 840 case DVACT_WAKEUP: 841 if (mainbus) { 842 rv = config_suspend(mainbus, act); 843 if (rv) 844 return rv; 845 } 846 if (mpath) 847 rv = config_suspend(mpath, act); 848 break; 849 } 850 851 return (rv); 852 } 853 854 /* 855 * Call the ca_activate for each of our children, letting each 856 * decide whether they wish to do the same for their children 857 * and more. 858 */ 859 int 860 config_activate_children(struct device *parent, int act) 861 { 862 struct device *d; 863 int rv = 0; 864 865 for (d = TAILQ_NEXT(parent, dv_list); d != NULL; 866 d = TAILQ_NEXT(d, dv_list)) { 867 if (d->dv_parent != parent) 868 continue; 869 switch (act) { 870 case DVACT_QUIESCE: 871 case DVACT_SUSPEND: 872 case DVACT_RESUME: 873 case DVACT_WAKEUP: 874 case DVACT_POWERDOWN: 875 rv = config_suspend(d, act); 876 break; 877 case DVACT_DEACTIVATE: 878 rv = config_deactivate(d); 879 break; 880 } 881 if (rv == 0) 882 continue; 883 884 /* 885 * Found a device that refuses the action. 886 * If we were being asked to suspend, we can 887 * try to resume all previous devices. 888 */ 889 #ifdef DIAGNOSTIC 890 printf("config_activate_children: device %s failed %d\n", 891 d->dv_xname, act); 892 #endif 893 if (act == DVACT_RESUME) 894 printf("failing resume cannot be handled\n"); 895 if (act == DVACT_POWERDOWN) 896 return (rv); 897 if (act != DVACT_SUSPEND) 898 return (rv); 899 900 d = TAILQ_PREV(d, devicelist, dv_list); 901 for (; d != NULL && d != parent; 902 d = TAILQ_PREV(d, devicelist, dv_list)) { 903 if (d->dv_parent != parent) 904 continue; 905 printf("resume %s\n", d->dv_xname); 906 config_suspend(d, DVACT_RESUME); 907 } 908 return (rv); 909 } 910 return (rv); 911 } 912 913 /* 914 * Lookup a device in the cfdriver device array. Does not return a 915 * device if it is not active. 916 * 917 * Increments ref count on the device by one, reflecting the 918 * new reference created on the stack. 919 * 920 * Context: process only 921 */ 922 struct device * 923 device_lookup(struct cfdriver *cd, int unit) 924 { 925 struct device *dv = NULL; 926 927 if (unit >= 0 && unit < cd->cd_ndevs) 928 dv = (struct device *)(cd->cd_devs[unit]); 929 930 if (!dv) 931 return (NULL); 932 933 if (!(dv->dv_flags & DVF_ACTIVE)) 934 dv = NULL; 935 936 if (dv != NULL) 937 device_ref(dv); 938 939 return (dv); 940 } 941 942 struct device * 943 device_mainbus(void) 944 { 945 extern struct cfdriver mainbus_cd; 946 947 if (mainbus_cd.cd_ndevs < 1) 948 return (NULL); 949 950 return (mainbus_cd.cd_devs[0]); 951 } 952 953 struct device * 954 device_mpath(void) 955 { 956 #if NMPATH > 0 957 extern struct cfdriver mpath_cd; 958 959 if (mpath_cd.cd_ndevs < 1) 960 return (NULL); 961 962 return (mpath_cd.cd_devs[0]); 963 #else 964 return (NULL); 965 #endif 966 } 967 968 /* 969 * Increments the ref count on the device structure. The device 970 * structure is freed when the ref count hits 0. 971 * 972 * Context: process or interrupt 973 */ 974 void 975 device_ref(struct device *dv) 976 { 977 atomic_inc_int(&dv->dv_ref); 978 } 979 980 /* 981 * Decrement the ref count on the device structure. 982 * 983 * free's the structure when the ref count hits zero. 984 * 985 * Context: process or interrupt 986 */ 987 void 988 device_unref(struct device *dv) 989 { 990 struct cfattach *ca; 991 992 if (atomic_dec_int_nv(&dv->dv_ref) == 0) { 993 ca = dv->dv_cfdata->cf_attach; 994 free(dv, M_DEVBUF, ca->ca_devsize); 995 } 996 } 997