xref: /openbsd-src/sys/kern/subr_autoconf.c (revision ef89f9e63174a1a2a3a51b4fe036c160c283438f)
1 /*	$OpenBSD: subr_autoconf.c,v 1.90 2015/12/11 16:07:02 mpi 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, (char *)0);
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, 0);
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, 0);
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