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