xref: /openbsd-src/sys/kern/subr_autoconf.c (revision 2df76cc2a0aee2cb2166e3799b7bb5c3f883f83d)
1 /*	$OpenBSD: subr_autoconf.c,v 1.75 2014/03/29 18:09:31 guenther 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 doesn't
527 	 * have an activation entry point, we allow DVF_ACTIVE to
528 	 * remain set.  Otherwise, if DVF_ACTIVE is still set, the
529 	 * device is busy, and the detach fails.
530 	 */
531 	if (ca->ca_activate != NULL)
532 		rv = config_deactivate(dev);
533 
534 	/*
535 	 * Try to detach the device.  If that's not possible, then
536 	 * we either panic() (for the forced but failed case), or
537 	 * return an error.
538 	 */
539 	if (rv == 0) {
540 		if (ca->ca_detach != NULL)
541 			rv = (*ca->ca_detach)(dev, flags);
542 		else
543 			rv = EOPNOTSUPP;
544 	}
545 	if (rv != 0) {
546 		if ((flags & DETACH_FORCE) == 0)
547 			goto done;
548 		else
549 			panic("config_detach: forced detach of %s failed (%d)",
550 			    dev->dv_xname, rv);
551 	}
552 
553 	/*
554 	 * The device has now been successfully detached.
555 	 */
556 
557 #ifdef DIAGNOSTIC
558 	/*
559 	 * Sanity: If you're successfully detached, you should have no
560 	 * children.  (Note that because children must be attached
561 	 * after parents, we only need to search the latter part of
562 	 * the list.)
563 	 */
564 	i = 0;
565 	for (d = TAILQ_NEXT(dev, dv_list); d != NULL;
566 	     d = TAILQ_NEXT(d, dv_list)) {
567 		if (d->dv_parent == dev) {
568 			printf("config_detach: %s attached at %s\n",
569 			    d->dv_xname, dev->dv_xname);
570 			i = 1;
571 		}
572 	}
573 	if (i != 0)
574 		panic("config_detach: detached device (%s) has children",
575 		    dev->dv_xname);
576 #endif
577 
578 	/*
579 	 * Mark cfdata to show that the unit can be reused, if possible.
580 	 * Note that we can only re-use a starred unit number if the unit
581 	 * being detached had the last assigned unit number.
582 	 */
583 	for (cf = cfdata; cf->cf_driver; cf++) {
584 		if (cf->cf_driver == cd) {
585 			if (cf->cf_fstate == FSTATE_FOUND &&
586 			    cf->cf_unit == dev->dv_unit)
587 				cf->cf_fstate = FSTATE_NOTFOUND;
588 			if (cf->cf_fstate == FSTATE_STAR &&
589 			    cf->cf_unit == dev->dv_unit + 1)
590 				cf->cf_unit--;
591 		}
592 	}
593 
594 	/*
595 	 * Unlink from device list.
596 	 */
597 	TAILQ_REMOVE(&alldevs, dev, dv_list);
598 	device_unref(dev);
599 
600 	/*
601 	 * Remove from cfdriver's array, tell the world, and free softc.
602 	 */
603 	cd->cd_devs[dev->dv_unit] = NULL;
604 	if ((flags & DETACH_QUIET) == 0)
605 		printf("%s detached\n", dev->dv_xname);
606 
607 	device_unref(dev);
608 	/*
609 	 * If the device now has no units in use, deallocate its softc array.
610 	 */
611 	for (i = 0; i < cd->cd_ndevs; i++)
612 		if (cd->cd_devs[i] != NULL)
613 			break;
614 	if (i == cd->cd_ndevs) {		/* nothing found; deallocate */
615 		free(cd->cd_devs, M_DEVBUF);
616 		cd->cd_devs = NULL;
617 		cd->cd_ndevs = 0;
618 		cf->cf_unit = 0;
619 	}
620 
621 #if NHOTPLUG > 0
622 	if (!cold)
623 		hotplug_device_detach(cd->cd_class, devname);
624 #endif
625 
626 	/*
627 	 * Return success.
628 	 */
629 done:
630 	mtx_enter(&autoconf_attdet_mtx);
631 	if (++autoconf_attdet == 0)
632 		wakeup(&autoconf_attdet);
633 	mtx_leave(&autoconf_attdet_mtx);
634 	return (rv);
635 }
636 
637 int
638 config_deactivate(struct device *dev)
639 {
640 	struct cfattach *ca = dev->dv_cfdata->cf_attach;
641 	int rv = 0, oflags = dev->dv_flags;
642 
643 	if (ca->ca_activate == NULL)
644 		return (EOPNOTSUPP);
645 
646 	if (dev->dv_flags & DVF_ACTIVE) {
647 		dev->dv_flags &= ~DVF_ACTIVE;
648 		rv = (*ca->ca_activate)(dev, DVACT_DEACTIVATE);
649 		if (rv)
650 			dev->dv_flags = oflags;
651 	}
652 	return (rv);
653 }
654 
655 /*
656  * Defer the configuration of the specified device until all
657  * of its parent's devices have been attached.
658  */
659 void
660 config_defer(struct device *dev, void (*func)(struct device *))
661 {
662 	struct deferred_config *dc;
663 
664 	if (dev->dv_parent == NULL)
665 		panic("config_defer: can't defer config of a root device");
666 
667 #ifdef DIAGNOSTIC
668 	for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL;
669 	     dc = TAILQ_NEXT(dc, dc_queue)) {
670 		if (dc->dc_dev == dev)
671 			panic("config_defer: deferred twice");
672 	}
673 #endif
674 
675 	if ((dc = malloc(sizeof(*dc), M_DEVBUF, M_NOWAIT)) == NULL)
676 		panic("config_defer: can't allocate defer structure");
677 
678 	dc->dc_dev = dev;
679 	dc->dc_func = func;
680 	TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue);
681 	config_pending_incr();
682 }
683 
684 /*
685  * Process the deferred configuration queue for a device.
686  */
687 void
688 config_process_deferred_children(struct device *parent)
689 {
690 	struct deferred_config *dc, *ndc;
691 
692 	for (dc = TAILQ_FIRST(&deferred_config_queue);
693 	     dc != NULL; dc = ndc) {
694 		ndc = TAILQ_NEXT(dc, dc_queue);
695 		if (dc->dc_dev->dv_parent == parent) {
696 			TAILQ_REMOVE(&deferred_config_queue, dc, dc_queue);
697 			(*dc->dc_func)(dc->dc_dev);
698 			free(dc, M_DEVBUF);
699 			config_pending_decr();
700 		}
701 	}
702 }
703 
704 /*
705  * Manipulate the config_pending semaphore.
706  */
707 void
708 config_pending_incr(void)
709 {
710 
711 	config_pending++;
712 }
713 
714 void
715 config_pending_decr(void)
716 {
717 
718 #ifdef DIAGNOSTIC
719 	if (config_pending == 0)
720 		panic("config_pending_decr: config_pending == 0");
721 #endif
722 	config_pending--;
723 	if (config_pending == 0)
724 		wakeup((void *)&config_pending);
725 }
726 
727 int
728 config_detach_children(struct device *parent, int flags)
729 {
730 	struct device *dev, *next_dev;
731 	int rv = 0;
732 
733 	/*
734 	 * The config_detach routine may sleep, meaning devices
735 	 * may be added to the queue. However, all devices will
736 	 * be added to the tail of the queue, the queue won't
737 	 * be re-organized, and the subtree of parent here should be locked
738 	 * for purposes of adding/removing children.
739 	 *
740 	 * Note that we can not afford trying to walk the device list
741 	 * once - our ``next'' device might be a child of the device
742 	 * we are about to detach, so it would disappear.
743 	 * Just play it safe and restart from the parent.
744 	 */
745 	for (dev = TAILQ_LAST(&alldevs, devicelist);
746 	    dev != NULL; dev = next_dev) {
747 		if (dev->dv_parent == parent) {
748 			if ((rv = config_detach(dev, flags)) != 0)
749 				return (rv);
750 			next_dev = TAILQ_LAST(&alldevs, devicelist);
751 		} else {
752 			next_dev = TAILQ_PREV(dev, devicelist, dv_list);
753 		}
754 	}
755 
756 	return (0);
757 }
758 
759 int
760 config_suspend(struct device *dev, int act)
761 {
762 	struct cfattach *ca = dev->dv_cfdata->cf_attach;
763 	int r;
764 
765 	device_ref(dev);
766 	if (ca->ca_activate)
767 		r = (*ca->ca_activate)(dev, act);
768 	else
769 		r = config_activate_children(dev, act);
770 	device_unref(dev);
771 	return (r);
772 }
773 
774 /*
775  * Call the ca_activate for each of our children, letting each
776  * decide whether they wish to do the same for their children
777  * and more.
778  */
779 int
780 config_activate_children(struct device *parent, int act)
781 {
782 	struct device *d;
783 	int rv = 0;
784 
785 	for (d = TAILQ_NEXT(parent, dv_list); d != NULL;
786 	    d = TAILQ_NEXT(d, dv_list)) {
787 		if (d->dv_parent != parent)
788 			continue;
789 		switch (act) {
790 		case DVACT_QUIESCE:
791 		case DVACT_SUSPEND:
792 		case DVACT_RESUME:
793 		case DVACT_WAKEUP:
794 		case DVACT_POWERDOWN:
795 			rv = config_suspend(d, act);
796 			break;
797 		case DVACT_DEACTIVATE:
798 			rv = config_deactivate(d);
799 			break;
800 		}
801 		if (rv == 0)
802 			continue;
803 
804 		/*
805 		 * Found a device that refuses the action.
806 		 * If we were being asked to suspend, we can
807 		 * try to resume all previous devices.
808 		 */
809 #ifdef DIAGNOSTIC
810 		printf("config_activate_children: device %s failed %d\n",
811 		    d->dv_xname, act);
812 #endif
813 		if (act == DVACT_RESUME)
814 			printf("failing resume cannot be handled\n");
815 		if (act == DVACT_POWERDOWN)
816 			return (rv);
817 		if (act != DVACT_SUSPEND)
818 			return (rv);
819 
820 		d = TAILQ_PREV(d, devicelist, dv_list);
821 		for (; d != NULL && d != parent;
822 		    d = TAILQ_PREV(d, devicelist, dv_list)) {
823 			if (d->dv_parent != parent)
824 				continue;
825 			printf("resume %s\n", d->dv_xname);
826 			config_suspend(d, DVACT_RESUME);
827 		}
828 		return (rv);
829 	}
830 	return (rv);
831 }
832 
833 /*
834  * Lookup a device in the cfdriver device array.  Does not return a
835  * device if it is not active.
836  *
837  * Increments ref count on the device by one, reflecting the
838  * new reference created on the stack.
839  *
840  * Context: process only
841  */
842 struct device *
843 device_lookup(struct cfdriver *cd, int unit)
844 {
845 	struct device *dv = NULL;
846 
847 	if (unit >= 0 && unit < cd->cd_ndevs)
848 		dv = (struct device *)(cd->cd_devs[unit]);
849 
850 	if (!dv)
851 		return (NULL);
852 
853 	if (!(dv->dv_flags & DVF_ACTIVE))
854 		dv = NULL;
855 
856 	if (dv != NULL)
857 		device_ref(dv);
858 
859 	return (dv);
860 }
861 
862 struct device *
863 device_mainbus(void)
864 {
865 	extern struct cfdriver mainbus_cd;
866 
867 	if (mainbus_cd.cd_ndevs < 1)
868 		return (NULL);
869 
870 	return (mainbus_cd.cd_devs[0]);
871 }
872 
873 /*
874  * Increments the ref count on the device structure. The device
875  * structure is freed when the ref count hits 0.
876  *
877  * Context: process or interrupt
878  */
879 void
880 device_ref(struct device *dv)
881 {
882 	dv->dv_ref++;
883 }
884 
885 /*
886  * Decrement the ref count on the device structure.
887  *
888  * free's the structure when the ref count hits zero.
889  *
890  * Context: process or interrupt
891  */
892 void
893 device_unref(struct device *dv)
894 {
895 	dv->dv_ref--;
896 	if (dv->dv_ref == 0) {
897 		free(dv, M_DEVBUF);
898 	}
899 }
900