xref: /openbsd-src/sys/kern/subr_autoconf.c (revision b62fa43dda8392a2ab20a61a95151a4dd30a8c8c)
1 /*	$OpenBSD: subr_autoconf.c,v 1.76 2014/07/12 13:43:08 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/limits.h>
50 #include <sys/malloc.h>
51 #include <sys/systm.h>
52 #include <sys/queue.h>
53 #include <sys/proc.h>
54 #include <sys/mutex.h>
55 
56 #include "hotplug.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 
92 void config_process_deferred_children(struct device *);
93 
94 struct devicelist alldevs;		/* list of all devices */
95 
96 volatile int config_pending;		/* semaphore for mountroot */
97 
98 struct mutex autoconf_attdet_mtx = MUTEX_INITIALIZER(IPL_HIGH);
99 /*
100  * If > 0, devices are being attached and any thread which tries to
101  * detach will sleep; if < 0 devices are being detached and any
102  * thread which tries to attach will sleep.
103  */
104 int	autoconf_attdet;
105 
106 /*
107  * Initialize autoconfiguration data structures.  This occurs before console
108  * initialization as that might require use of this subsystem.  Furthermore
109  * this means that malloc et al. isn't yet available.
110  */
111 void
112 config_init(void)
113 {
114 	TAILQ_INIT(&deferred_config_queue);
115 	TAILQ_INIT(&alldevs);
116 }
117 
118 /*
119  * Apply the matching function and choose the best.  This is used
120  * a few times and we want to keep the code small.
121  */
122 void
123 mapply(struct matchinfo *m, struct cfdata *cf)
124 {
125 	int pri;
126 	void *match;
127 
128 	if (m->indirect)
129 		match = config_make_softc(m->parent, cf);
130 	else
131 		match = cf;
132 
133 	if (autoconf_verbose) {
134 		printf(">>> probing for %s", cf->cf_driver->cd_name);
135 		if (cf->cf_fstate == FSTATE_STAR)
136 			printf("*\n");
137 		else
138 			printf("%d\n", cf->cf_unit);
139 	}
140 	if (m->fn != NULL)
141 		pri = (*m->fn)(m->parent, match, m->aux);
142 	else {
143 	        if (cf->cf_attach->ca_match == NULL) {
144 			panic("mapply: no match function for '%s' device",
145 			    cf->cf_driver->cd_name);
146 		}
147 		pri = (*cf->cf_attach->ca_match)(m->parent, match, m->aux);
148 	}
149 	if (autoconf_verbose)
150 		printf(">>> %s probe returned %d\n", cf->cf_driver->cd_name,
151 		    pri);
152 
153 	if (pri > m->pri) {
154 		if (m->indirect && m->match)
155 			free(m->match, M_DEVBUF);
156 		m->match = match;
157 		m->pri = pri;
158 	} else {
159 		if (m->indirect)
160 			free(match, M_DEVBUF);
161 	}
162 }
163 
164 /*
165  * Iterate over all potential children of some device, calling the given
166  * function (default being the child's match function) for each one.
167  * Nonzero returns are matches; the highest value returned is considered
168  * the best match.  Return the `found child' if we got a match, or NULL
169  * otherwise.  The `aux' pointer is simply passed on through.
170  *
171  * Note that this function is designed so that it can be used to apply
172  * an arbitrary function to all potential children (its return value
173  * can be ignored).
174  */
175 void *
176 config_search(cfmatch_t fn, struct device *parent, void *aux)
177 {
178 	struct cfdata *cf;
179 	short *p;
180 	struct matchinfo m;
181 
182 	m.fn = fn;
183 	m.parent = parent;
184 	m.match = NULL;
185 	m.aux = aux;
186 	m.indirect = parent && parent->dv_cfdata->cf_driver->cd_indirect;
187 	m.pri = 0;
188 
189 	for (cf = cfdata; cf->cf_driver; cf++) {
190 		/*
191 		 * Skip cf if no longer eligible, otherwise scan
192 		 * through parents for one matching `parent',
193 		 * and try match function.
194 		 */
195 		if (cf->cf_fstate == FSTATE_FOUND)
196 			continue;
197 		if (cf->cf_fstate == FSTATE_DNOTFOUND ||
198 		    cf->cf_fstate == FSTATE_DSTAR)
199 			continue;
200 		for (p = cf->cf_parents; *p >= 0; p++)
201 			if (parent->dv_cfdata == &cfdata[*p])
202 				mapply(&m, cf);
203 	}
204 
205 	if (autoconf_verbose) {
206 		if (m.match) {
207 			if (m.indirect)
208 				cf = ((struct device *)m.match)->dv_cfdata;
209 			else
210 				cf = (struct cfdata *)m.match;
211 			printf(">>> %s probe won\n",
212 			    cf->cf_driver->cd_name);
213 		} else
214 			printf(">>> no winning probe\n");
215 	}
216 	return (m.match);
217 }
218 
219 /*
220  * Iterate over all potential children of some device, calling the given
221  * function for each one.
222  *
223  * Note that this function is designed so that it can be used to apply
224  * an arbitrary function to all potential children (its return value
225  * can be ignored).
226  */
227 void
228 config_scan(cfscan_t fn, struct device *parent)
229 {
230 	struct cfdata *cf;
231 	short *p;
232 	void *match;
233 	int indirect;
234 
235 	indirect = parent && parent->dv_cfdata->cf_driver->cd_indirect;
236 
237 	for (cf = cfdata; cf->cf_driver; cf++) {
238 		/*
239 		 * Skip cf if no longer eligible, otherwise scan
240 		 * through parents for one matching `parent',
241 		 * and try match function.
242 		 */
243 		if (cf->cf_fstate == FSTATE_FOUND)
244 			continue;
245 		if (cf->cf_fstate == FSTATE_DNOTFOUND ||
246 		    cf->cf_fstate == FSTATE_DSTAR)
247 			continue;
248 		for (p = cf->cf_parents; *p >= 0; p++)
249 			if (parent->dv_cfdata == &cfdata[*p]) {
250 				match = indirect?
251 				    config_make_softc(parent, cf) :
252 				    (void *)cf;
253 				(*fn)(parent, match);
254 			}
255 	}
256 }
257 
258 /*
259  * Find the given root device.
260  * This is much like config_search, but there is no parent.
261  */
262 void *
263 config_rootsearch(cfmatch_t fn, char *rootname, void *aux)
264 {
265 	struct cfdata *cf;
266 	short *p;
267 	struct matchinfo m;
268 
269 	m.fn = fn;
270 	m.parent = ROOT;
271 	m.match = NULL;
272 	m.aux = aux;
273 	m.indirect = 0;
274 	m.pri = 0;
275 	/*
276 	 * Look at root entries for matching name.  We do not bother
277 	 * with found-state here since only one instance of each possible
278 	 * root child should ever be searched.
279 	 */
280 	for (p = cfroots; *p >= 0; p++) {
281 		cf = &cfdata[*p];
282 		if (cf->cf_fstate == FSTATE_DNOTFOUND ||
283 		    cf->cf_fstate == FSTATE_DSTAR)
284 			continue;
285 		if (strcmp(cf->cf_driver->cd_name, rootname) == 0)
286 			mapply(&m, cf);
287 	}
288 	return (m.match);
289 }
290 
291 const char *msgs[3] = { "", " not configured\n", " unsupported\n" };
292 
293 /*
294  * The given `aux' argument describes a device that has been found
295  * on the given parent, but not necessarily configured.  Locate the
296  * configuration data for that device (using the submatch function
297  * provided, or using candidates' cd_match configuration driver
298  * functions) and attach it, and return true.  If the device was
299  * not configured, call the given `print' function and return 0.
300  */
301 struct device *
302 config_found_sm(struct device *parent, void *aux, cfprint_t print,
303     cfmatch_t submatch)
304 {
305 	void *match;
306 
307 	if ((match = config_search(submatch, parent, aux)) != NULL)
308 		return (config_attach(parent, match, aux, print));
309 	if (print)
310 		printf("%s", msgs[(*print)(aux, parent->dv_xname)]);
311 	return (NULL);
312 }
313 
314 /*
315  * As above, but for root devices.
316  */
317 struct device *
318 config_rootfound(char *rootname, void *aux)
319 {
320 	void *match;
321 
322 	if ((match = config_rootsearch((cfmatch_t)NULL, rootname, aux)) != NULL)
323 		return (config_attach(ROOT, match, aux, (cfprint_t)NULL));
324 	printf("root device %s not configured\n", rootname);
325 	return (NULL);
326 }
327 
328 /*
329  * Attach a found device.  Allocates memory for device variables.
330  */
331 struct device *
332 config_attach(struct device *parent, void *match, void *aux, cfprint_t print)
333 {
334 	struct cfdata *cf;
335 	struct device *dev;
336 	struct cfdriver *cd;
337 	struct cfattach *ca;
338 
339 	mtx_enter(&autoconf_attdet_mtx);
340 	while (autoconf_attdet < 0)
341 		msleep(&autoconf_attdet, &autoconf_attdet_mtx,
342 		    PWAIT, "autoconf", 0);
343 	autoconf_attdet++;
344 	mtx_leave(&autoconf_attdet_mtx);
345 
346 	if (parent && parent->dv_cfdata->cf_driver->cd_indirect) {
347 		dev = match;
348 		cf = dev->dv_cfdata;
349 	} else {
350 		cf = match;
351 		dev = config_make_softc(parent, cf);
352 	}
353 
354 	cd = cf->cf_driver;
355 	ca = cf->cf_attach;
356 
357 	KASSERT(cd->cd_devs != NULL);
358 	KASSERT(dev->dv_unit < cd->cd_ndevs);
359 	KASSERT(cd->cd_devs[dev->dv_unit] == NULL);
360 	cd->cd_devs[dev->dv_unit] = dev;
361 
362 	/*
363 	 * If this is a "STAR" device and we used the last unit, prepare for
364 	 * another one.
365 	 */
366 	if (cf->cf_fstate == FSTATE_STAR) {
367 		if (dev->dv_unit == cf->cf_unit)
368 			cf->cf_unit++;
369 	} else
370 		cf->cf_fstate = FSTATE_FOUND;
371 
372 	TAILQ_INSERT_TAIL(&alldevs, dev, dv_list);
373 	device_ref(dev);
374 
375 	if (parent == ROOT)
376 		printf("%s at root", dev->dv_xname);
377 	else {
378 		printf("%s at %s", dev->dv_xname, parent->dv_xname);
379 		if (print)
380 			(void) (*print)(aux, (char *)0);
381 	}
382 
383 	/*
384 	 * Before attaching, clobber any unfound devices that are
385 	 * otherwise identical, or bump the unit number on all starred
386 	 * cfdata for this device.
387 	 */
388 	for (cf = cfdata; cf->cf_driver; cf++) {
389 		if (cf->cf_driver == cd &&
390 		    cf->cf_unit == dev->dv_unit) {
391 			if (cf->cf_fstate == FSTATE_NOTFOUND)
392 				cf->cf_fstate = FSTATE_FOUND;
393 			if (cf->cf_fstate == FSTATE_STAR)
394 				cf->cf_unit++;
395 		}
396 	}
397 	device_register(dev, aux);
398 	(*ca->ca_attach)(parent, dev, aux);
399 	config_process_deferred_children(dev);
400 #if NHOTPLUG > 0
401 	if (!cold)
402 		hotplug_device_attach(cd->cd_class, dev->dv_xname);
403 #endif
404 
405 	mtx_enter(&autoconf_attdet_mtx);
406 	if (--autoconf_attdet == 0)
407 		wakeup(&autoconf_attdet);
408 	mtx_leave(&autoconf_attdet_mtx);
409 	return (dev);
410 }
411 
412 struct device *
413 config_make_softc(struct device *parent, struct cfdata *cf)
414 {
415 	struct device *dev;
416 	struct cfdriver *cd;
417 	struct cfattach *ca;
418 
419 	cd = cf->cf_driver;
420 	ca = cf->cf_attach;
421 	if (ca->ca_devsize < sizeof(struct device))
422 		panic("config_make_softc");
423 
424 	/* get memory for all device vars */
425 	dev = malloc(ca->ca_devsize, M_DEVBUF, M_NOWAIT|M_ZERO);
426 	if (dev == NULL)
427 		panic("config_make_softc: allocation for device softc failed");
428 
429 	dev->dv_class = cd->cd_class;
430 	dev->dv_cfdata = cf;
431 	dev->dv_flags = DVF_ACTIVE;	/* always initially active */
432 
433 	/* If this is a STAR device, search for a free unit number */
434 	if (cf->cf_fstate == FSTATE_STAR) {
435 		for (dev->dv_unit = cf->cf_starunit1;
436 		    dev->dv_unit < cf->cf_unit; dev->dv_unit++)
437 			if (cd->cd_ndevs == 0 ||
438 			    dev->dv_unit >= cd->cd_ndevs ||
439 			    cd->cd_devs[dev->dv_unit] == NULL)
440 				break;
441 	} else
442 		dev->dv_unit = cf->cf_unit;
443 
444 	/* Build the device name into dv_xname. */
445 	if (snprintf(dev->dv_xname, sizeof(dev->dv_xname), "%s%d",
446 	    cd->cd_name, dev->dv_unit) >= sizeof(dev->dv_xname))
447 		panic("config_make_softc: device name too long");
448 	dev->dv_parent = parent;
449 
450 	/* put this device in the devices array */
451 	if (dev->dv_unit >= cd->cd_ndevs) {
452 		/*
453 		 * Need to expand the array.
454 		 */
455 		int old = cd->cd_ndevs, new;
456 		void **nsp;
457 
458 		if (old == 0)
459 			new = MINALLOCSIZE / sizeof(void *);
460 		else
461 			new = old * 2;
462 		while (new <= dev->dv_unit)
463 			new *= 2;
464 		cd->cd_ndevs = new;
465 		nsp = malloc(new * sizeof(void *), M_DEVBUF, M_NOWAIT|M_ZERO);
466 		if (nsp == NULL)
467 			panic("config_make_softc: %sing dev array",
468 			    old != 0 ? "expand" : "creat");
469 		if (old != 0) {
470 			bcopy(cd->cd_devs, nsp, old * sizeof(void *));
471 			free(cd->cd_devs, M_DEVBUF);
472 		}
473 		cd->cd_devs = nsp;
474 	}
475 	if (cd->cd_devs[dev->dv_unit])
476 		panic("config_make_softc: duplicate %s", dev->dv_xname);
477 
478 	dev->dv_ref = 1;
479 
480 	return (dev);
481 }
482 
483 /*
484  * Detach a device.  Optionally forced (e.g. because of hardware
485  * removal) and quiet.  Returns zero if successful, non-zero
486  * (an error code) otherwise.
487  *
488  * Note that this code wants to be run from a process context, so
489  * that the detach can sleep to allow processes which have a device
490  * open to run and unwind their stacks.
491  */
492 int
493 config_detach(struct device *dev, int flags)
494 {
495 	struct cfdata *cf;
496 	struct cfattach *ca;
497 	struct cfdriver *cd;
498 	int rv = 0, i;
499 #ifdef DIAGNOSTIC
500 	struct device *d;
501 #endif
502 #if NHOTPLUG > 0
503 	char devname[16];
504 #endif
505 
506 	mtx_enter(&autoconf_attdet_mtx);
507 	while (autoconf_attdet > 0)
508 		msleep(&autoconf_attdet, &autoconf_attdet_mtx,
509 		    PWAIT, "autoconf", 0);
510 	autoconf_attdet--;
511 	mtx_leave(&autoconf_attdet_mtx);
512 
513 #if NHOTPLUG > 0
514 	strlcpy(devname, dev->dv_xname, sizeof(devname));
515 #endif
516 
517 	cf = dev->dv_cfdata;
518 #ifdef DIAGNOSTIC
519 	if (cf->cf_fstate != FSTATE_FOUND && cf->cf_fstate != FSTATE_STAR)
520 		panic("config_detach: bad device fstate");
521 #endif
522 	ca = cf->cf_attach;
523 	cd = cf->cf_driver;
524 
525 	/*
526 	 * Ensure the device is deactivated.  If the device has an
527 	 * activation entry point and DVF_ACTIVE is still set, the
528 	 * device is busy, and the detach fails.
529 	 */
530 	rv = config_deactivate(dev);
531 
532 	/*
533 	 * Try to detach the device.  If that's not possible, then
534 	 * we either panic() (for the forced but failed case), or
535 	 * return an error.
536 	 */
537 	if (rv == 0) {
538 		if (ca->ca_detach != NULL)
539 			rv = (*ca->ca_detach)(dev, flags);
540 		else
541 			rv = EOPNOTSUPP;
542 	}
543 	if (rv != 0) {
544 		if ((flags & DETACH_FORCE) == 0)
545 			goto done;
546 		else
547 			panic("config_detach: forced detach of %s failed (%d)",
548 			    dev->dv_xname, rv);
549 	}
550 
551 	/*
552 	 * The device has now been successfully detached.
553 	 */
554 
555 #ifdef DIAGNOSTIC
556 	/*
557 	 * Sanity: If you're successfully detached, you should have no
558 	 * children.  (Note that because children must be attached
559 	 * after parents, we only need to search the latter part of
560 	 * the list.)
561 	 */
562 	i = 0;
563 	for (d = TAILQ_NEXT(dev, dv_list); d != NULL;
564 	     d = TAILQ_NEXT(d, dv_list)) {
565 		if (d->dv_parent == dev) {
566 			printf("config_detach: %s attached at %s\n",
567 			    d->dv_xname, dev->dv_xname);
568 			i = 1;
569 		}
570 	}
571 	if (i != 0)
572 		panic("config_detach: detached device (%s) has children",
573 		    dev->dv_xname);
574 #endif
575 
576 	/*
577 	 * Mark cfdata to show that the unit can be reused, if possible.
578 	 * Note that we can only re-use a starred unit number if the unit
579 	 * being detached had the last assigned unit number.
580 	 */
581 	for (cf = cfdata; cf->cf_driver; cf++) {
582 		if (cf->cf_driver == cd) {
583 			if (cf->cf_fstate == FSTATE_FOUND &&
584 			    cf->cf_unit == dev->dv_unit)
585 				cf->cf_fstate = FSTATE_NOTFOUND;
586 			if (cf->cf_fstate == FSTATE_STAR &&
587 			    cf->cf_unit == dev->dv_unit + 1)
588 				cf->cf_unit--;
589 		}
590 	}
591 
592 	/*
593 	 * Unlink from device list.
594 	 */
595 	TAILQ_REMOVE(&alldevs, dev, dv_list);
596 	device_unref(dev);
597 
598 	/*
599 	 * Remove from cfdriver's array, tell the world, and free softc.
600 	 */
601 	cd->cd_devs[dev->dv_unit] = NULL;
602 	if ((flags & DETACH_QUIET) == 0)
603 		printf("%s detached\n", dev->dv_xname);
604 
605 	device_unref(dev);
606 	/*
607 	 * If the device now has no units in use, deallocate its softc array.
608 	 */
609 	for (i = 0; i < cd->cd_ndevs; i++)
610 		if (cd->cd_devs[i] != NULL)
611 			break;
612 	if (i == cd->cd_ndevs) {		/* nothing found; deallocate */
613 		free(cd->cd_devs, M_DEVBUF);
614 		cd->cd_devs = NULL;
615 		cd->cd_ndevs = 0;
616 		cf->cf_unit = 0;
617 	}
618 
619 #if NHOTPLUG > 0
620 	if (!cold)
621 		hotplug_device_detach(cd->cd_class, devname);
622 #endif
623 
624 	/*
625 	 * Return success.
626 	 */
627 done:
628 	mtx_enter(&autoconf_attdet_mtx);
629 	if (++autoconf_attdet == 0)
630 		wakeup(&autoconf_attdet);
631 	mtx_leave(&autoconf_attdet_mtx);
632 	return (rv);
633 }
634 
635 int
636 config_deactivate(struct device *dev)
637 {
638 	int rv = 0, oflags = dev->dv_flags;
639 
640 	if (dev->dv_flags & DVF_ACTIVE) {
641 		dev->dv_flags &= ~DVF_ACTIVE;
642 		rv = config_suspend(dev, DVACT_DEACTIVATE);
643 		if (rv)
644 			dev->dv_flags = oflags;
645 	}
646 	return (rv);
647 }
648 
649 /*
650  * Defer the configuration of the specified device until all
651  * of its parent's devices have been attached.
652  */
653 void
654 config_defer(struct device *dev, void (*func)(struct device *))
655 {
656 	struct deferred_config *dc;
657 
658 	if (dev->dv_parent == NULL)
659 		panic("config_defer: can't defer config of a root device");
660 
661 #ifdef DIAGNOSTIC
662 	for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL;
663 	     dc = TAILQ_NEXT(dc, dc_queue)) {
664 		if (dc->dc_dev == dev)
665 			panic("config_defer: deferred twice");
666 	}
667 #endif
668 
669 	if ((dc = malloc(sizeof(*dc), M_DEVBUF, M_NOWAIT)) == NULL)
670 		panic("config_defer: can't allocate defer structure");
671 
672 	dc->dc_dev = dev;
673 	dc->dc_func = func;
674 	TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue);
675 	config_pending_incr();
676 }
677 
678 /*
679  * Process the deferred configuration queue for a device.
680  */
681 void
682 config_process_deferred_children(struct device *parent)
683 {
684 	struct deferred_config *dc, *ndc;
685 
686 	for (dc = TAILQ_FIRST(&deferred_config_queue);
687 	     dc != NULL; dc = ndc) {
688 		ndc = TAILQ_NEXT(dc, dc_queue);
689 		if (dc->dc_dev->dv_parent == parent) {
690 			TAILQ_REMOVE(&deferred_config_queue, dc, dc_queue);
691 			(*dc->dc_func)(dc->dc_dev);
692 			free(dc, M_DEVBUF);
693 			config_pending_decr();
694 		}
695 	}
696 }
697 
698 /*
699  * Manipulate the config_pending semaphore.
700  */
701 void
702 config_pending_incr(void)
703 {
704 
705 	config_pending++;
706 }
707 
708 void
709 config_pending_decr(void)
710 {
711 
712 #ifdef DIAGNOSTIC
713 	if (config_pending == 0)
714 		panic("config_pending_decr: config_pending == 0");
715 #endif
716 	config_pending--;
717 	if (config_pending == 0)
718 		wakeup((void *)&config_pending);
719 }
720 
721 int
722 config_detach_children(struct device *parent, int flags)
723 {
724 	struct device *dev, *next_dev;
725 	int rv = 0;
726 
727 	/*
728 	 * The config_detach routine may sleep, meaning devices
729 	 * may be added to the queue. However, all devices will
730 	 * be added to the tail of the queue, the queue won't
731 	 * be re-organized, and the subtree of parent here should be locked
732 	 * for purposes of adding/removing children.
733 	 *
734 	 * Note that we can not afford trying to walk the device list
735 	 * once - our ``next'' device might be a child of the device
736 	 * we are about to detach, so it would disappear.
737 	 * Just play it safe and restart from the parent.
738 	 */
739 	for (dev = TAILQ_LAST(&alldevs, devicelist);
740 	    dev != NULL; dev = next_dev) {
741 		if (dev->dv_parent == parent) {
742 			if ((rv = config_detach(dev, flags)) != 0)
743 				return (rv);
744 			next_dev = TAILQ_LAST(&alldevs, devicelist);
745 		} else {
746 			next_dev = TAILQ_PREV(dev, devicelist, dv_list);
747 		}
748 	}
749 
750 	return (0);
751 }
752 
753 int
754 config_suspend(struct device *dev, int act)
755 {
756 	struct cfattach *ca = dev->dv_cfdata->cf_attach;
757 	int r;
758 
759 	device_ref(dev);
760 	if (ca->ca_activate)
761 		r = (*ca->ca_activate)(dev, act);
762 	else
763 		r = config_activate_children(dev, act);
764 	device_unref(dev);
765 	return (r);
766 }
767 
768 /*
769  * Call the ca_activate for each of our children, letting each
770  * decide whether they wish to do the same for their children
771  * and more.
772  */
773 int
774 config_activate_children(struct device *parent, int act)
775 {
776 	struct device *d;
777 	int rv = 0;
778 
779 	for (d = TAILQ_NEXT(parent, dv_list); d != NULL;
780 	    d = TAILQ_NEXT(d, dv_list)) {
781 		if (d->dv_parent != parent)
782 			continue;
783 		switch (act) {
784 		case DVACT_QUIESCE:
785 		case DVACT_SUSPEND:
786 		case DVACT_RESUME:
787 		case DVACT_WAKEUP:
788 		case DVACT_POWERDOWN:
789 			rv = config_suspend(d, act);
790 			break;
791 		case DVACT_DEACTIVATE:
792 			rv = config_deactivate(d);
793 			break;
794 		}
795 		if (rv == 0)
796 			continue;
797 
798 		/*
799 		 * Found a device that refuses the action.
800 		 * If we were being asked to suspend, we can
801 		 * try to resume all previous devices.
802 		 */
803 #ifdef DIAGNOSTIC
804 		printf("config_activate_children: device %s failed %d\n",
805 		    d->dv_xname, act);
806 #endif
807 		if (act == DVACT_RESUME)
808 			printf("failing resume cannot be handled\n");
809 		if (act == DVACT_POWERDOWN)
810 			return (rv);
811 		if (act != DVACT_SUSPEND)
812 			return (rv);
813 
814 		d = TAILQ_PREV(d, devicelist, dv_list);
815 		for (; d != NULL && d != parent;
816 		    d = TAILQ_PREV(d, devicelist, dv_list)) {
817 			if (d->dv_parent != parent)
818 				continue;
819 			printf("resume %s\n", d->dv_xname);
820 			config_suspend(d, DVACT_RESUME);
821 		}
822 		return (rv);
823 	}
824 	return (rv);
825 }
826 
827 /*
828  * Lookup a device in the cfdriver device array.  Does not return a
829  * device if it is not active.
830  *
831  * Increments ref count on the device by one, reflecting the
832  * new reference created on the stack.
833  *
834  * Context: process only
835  */
836 struct device *
837 device_lookup(struct cfdriver *cd, int unit)
838 {
839 	struct device *dv = NULL;
840 
841 	if (unit >= 0 && unit < cd->cd_ndevs)
842 		dv = (struct device *)(cd->cd_devs[unit]);
843 
844 	if (!dv)
845 		return (NULL);
846 
847 	if (!(dv->dv_flags & DVF_ACTIVE))
848 		dv = NULL;
849 
850 	if (dv != NULL)
851 		device_ref(dv);
852 
853 	return (dv);
854 }
855 
856 struct device *
857 device_mainbus(void)
858 {
859 	extern struct cfdriver mainbus_cd;
860 
861 	if (mainbus_cd.cd_ndevs < 1)
862 		return (NULL);
863 
864 	return (mainbus_cd.cd_devs[0]);
865 }
866 
867 /*
868  * Increments the ref count on the device structure. The device
869  * structure is freed when the ref count hits 0.
870  *
871  * Context: process or interrupt
872  */
873 void
874 device_ref(struct device *dv)
875 {
876 	dv->dv_ref++;
877 }
878 
879 /*
880  * Decrement the ref count on the device structure.
881  *
882  * free's the structure when the ref count hits zero.
883  *
884  * Context: process or interrupt
885  */
886 void
887 device_unref(struct device *dv)
888 {
889 	dv->dv_ref--;
890 	if (dv->dv_ref == 0) {
891 		free(dv, M_DEVBUF);
892 	}
893 }
894