Sun Apr 16 11:14:58 2023 UTC ()
autoconf(9): Avoid potential ABA bug in config_makeroom.

When we unlock alldevs_lock to allocate a new cd_devs array nsp,
other threads may have:

1. freed the old one (osp),
2. done some other memory allocation,
3. allocated a new _larger_ array whose address happens to concide
   with osp (e.g., in (2) the page was recycled for a different pool
   cache), and
4. updated cd_devs back to osp but increased cd_ndevs.

In that case, the memory may be corrupted: we try to copy the wrong
number of device_t pointers into nsp and we free osp with the wrong
(stale) length.

Avoid this by checking whether cd_ndevs has changed too -- if not,
osp might have been recycled but at least the lengths we're about to
copy and free are still correct so there's no harm in an ABA
situation.

XXX pullup-8
XXX pullup-9
XXX pullup-10


(riastradh)
diff -r1.307 -r1.308 src/sys/kern/subr_autoconf.c

cvs diff -r1.307 -r1.308 src/sys/kern/subr_autoconf.c (switch to unified diff)

--- src/sys/kern/subr_autoconf.c 2023/02/22 17:00:16 1.307
+++ src/sys/kern/subr_autoconf.c 2023/04/16 11:14:58 1.308
@@ -1,2359 +1,2359 @@ @@ -1,2359 +1,2359 @@
1/* $NetBSD: subr_autoconf.c,v 1.307 2023/02/22 17:00:16 riastradh Exp $ */ 1/* $NetBSD: subr_autoconf.c,v 1.308 2023/04/16 11:14:58 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1996, 2000 Christopher G. Demetriou 4 * Copyright (c) 1996, 2000 Christopher G. Demetriou
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement: 16 * must display the following acknowledgement:
17 * This product includes software developed for the 17 * This product includes software developed for the
18 * NetBSD Project. See http://www.NetBSD.org/ for 18 * NetBSD Project. See http://www.NetBSD.org/ for
19 * information about NetBSD. 19 * information about NetBSD.
20 * 4. The name of the author may not be used to endorse or promote products 20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission. 21 * derived from this software without specific prior written permission.
22 * 22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * 33 *
34 * --(license Id: LICENSE.proto,v 1.1 2000/06/13 21:40:26 cgd Exp )-- 34 * --(license Id: LICENSE.proto,v 1.1 2000/06/13 21:40:26 cgd Exp )--
35 */ 35 */
36 36
37/* 37/*
38 * Copyright (c) 1992, 1993 38 * Copyright (c) 1992, 1993
39 * The Regents of the University of California. All rights reserved. 39 * The Regents of the University of California. All rights reserved.
40 * 40 *
41 * This software was developed by the Computer Systems Engineering group 41 * This software was developed by the Computer Systems Engineering group
42 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 42 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
43 * contributed to Berkeley. 43 * contributed to Berkeley.
44 * 44 *
45 * All advertising materials mentioning features or use of this software 45 * All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement: 46 * must display the following acknowledgement:
47 * This product includes software developed by the University of 47 * This product includes software developed by the University of
48 * California, Lawrence Berkeley Laboratories. 48 * California, Lawrence Berkeley Laboratories.
49 * 49 *
50 * Redistribution and use in source and binary forms, with or without 50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions 51 * modification, are permitted provided that the following conditions
52 * are met: 52 * are met:
53 * 1. Redistributions of source code must retain the above copyright 53 * 1. Redistributions of source code must retain the above copyright
54 * notice, this list of conditions and the following disclaimer. 54 * notice, this list of conditions and the following disclaimer.
55 * 2. Redistributions in binary form must reproduce the above copyright 55 * 2. Redistributions in binary form must reproduce the above copyright
56 * notice, this list of conditions and the following disclaimer in the 56 * notice, this list of conditions and the following disclaimer in the
57 * documentation and/or other materials provided with the distribution. 57 * documentation and/or other materials provided with the distribution.
58 * 3. Neither the name of the University nor the names of its contributors 58 * 3. Neither the name of the University nor the names of its contributors
59 * may be used to endorse or promote products derived from this software 59 * may be used to endorse or promote products derived from this software
60 * without specific prior written permission. 60 * without specific prior written permission.
61 * 61 *
62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 * SUCH DAMAGE. 72 * SUCH DAMAGE.
73 * 73 *
74 * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp (LBL) 74 * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp (LBL)
75 * 75 *
76 * @(#)subr_autoconf.c 8.3 (Berkeley) 5/17/94 76 * @(#)subr_autoconf.c 8.3 (Berkeley) 5/17/94
77 */ 77 */
78 78
79#include <sys/cdefs.h> 79#include <sys/cdefs.h>
80__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.307 2023/02/22 17:00:16 riastradh Exp $"); 80__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.308 2023/04/16 11:14:58 riastradh Exp $");
81 81
82#ifdef _KERNEL_OPT 82#ifdef _KERNEL_OPT
83#include "opt_ddb.h" 83#include "opt_ddb.h"
84#include "drvctl.h" 84#include "drvctl.h"
85#endif 85#endif
86 86
87#include <sys/param.h> 87#include <sys/param.h>
88#include <sys/device.h> 88#include <sys/device.h>
89#include <sys/device_impl.h> 89#include <sys/device_impl.h>
90#include <sys/disklabel.h> 90#include <sys/disklabel.h>
91#include <sys/conf.h> 91#include <sys/conf.h>
92#include <sys/kauth.h> 92#include <sys/kauth.h>
93#include <sys/kmem.h> 93#include <sys/kmem.h>
94#include <sys/systm.h> 94#include <sys/systm.h>
95#include <sys/kernel.h> 95#include <sys/kernel.h>
96#include <sys/errno.h> 96#include <sys/errno.h>
97#include <sys/proc.h> 97#include <sys/proc.h>
98#include <sys/reboot.h> 98#include <sys/reboot.h>
99#include <sys/kthread.h> 99#include <sys/kthread.h>
100#include <sys/buf.h> 100#include <sys/buf.h>
101#include <sys/dirent.h> 101#include <sys/dirent.h>
102#include <sys/mount.h> 102#include <sys/mount.h>
103#include <sys/namei.h> 103#include <sys/namei.h>
104#include <sys/unistd.h> 104#include <sys/unistd.h>
105#include <sys/fcntl.h> 105#include <sys/fcntl.h>
106#include <sys/lockf.h> 106#include <sys/lockf.h>
107#include <sys/callout.h> 107#include <sys/callout.h>
108#include <sys/devmon.h> 108#include <sys/devmon.h>
109#include <sys/cpu.h> 109#include <sys/cpu.h>
110#include <sys/sysctl.h> 110#include <sys/sysctl.h>
111#include <sys/stdarg.h> 111#include <sys/stdarg.h>
112#include <sys/localcount.h> 112#include <sys/localcount.h>
113 113
114#include <sys/disk.h> 114#include <sys/disk.h>
115 115
116#include <sys/rndsource.h> 116#include <sys/rndsource.h>
117 117
118#include <machine/limits.h> 118#include <machine/limits.h>
119 119
120/* 120/*
121 * Autoconfiguration subroutines. 121 * Autoconfiguration subroutines.
122 */ 122 */
123 123
124/* 124/*
125 * Device autoconfiguration timings are mixed into the entropy pool. 125 * Device autoconfiguration timings are mixed into the entropy pool.
126 */ 126 */
127static krndsource_t rnd_autoconf_source; 127static krndsource_t rnd_autoconf_source;
128 128
129/* 129/*
130 * ioconf.c exports exactly two names: cfdata and cfroots. All system 130 * ioconf.c exports exactly two names: cfdata and cfroots. All system
131 * devices and drivers are found via these tables. 131 * devices and drivers are found via these tables.
132 */ 132 */
133extern struct cfdata cfdata[]; 133extern struct cfdata cfdata[];
134extern const short cfroots[]; 134extern const short cfroots[];
135 135
136/* 136/*
137 * List of all cfdriver structures. We use this to detect duplicates 137 * List of all cfdriver structures. We use this to detect duplicates
138 * when other cfdrivers are loaded. 138 * when other cfdrivers are loaded.
139 */ 139 */
140struct cfdriverlist allcfdrivers = LIST_HEAD_INITIALIZER(&allcfdrivers); 140struct cfdriverlist allcfdrivers = LIST_HEAD_INITIALIZER(&allcfdrivers);
141extern struct cfdriver * const cfdriver_list_initial[]; 141extern struct cfdriver * const cfdriver_list_initial[];
142 142
143/* 143/*
144 * Initial list of cfattach's. 144 * Initial list of cfattach's.
145 */ 145 */
146extern const struct cfattachinit cfattachinit[]; 146extern const struct cfattachinit cfattachinit[];
147 147
148/* 148/*
149 * List of cfdata tables. We always have one such list -- the one 149 * List of cfdata tables. We always have one such list -- the one
150 * built statically when the kernel was configured. 150 * built statically when the kernel was configured.
151 */ 151 */
152struct cftablelist allcftables = TAILQ_HEAD_INITIALIZER(allcftables); 152struct cftablelist allcftables = TAILQ_HEAD_INITIALIZER(allcftables);
153static struct cftable initcftable; 153static struct cftable initcftable;
154 154
155#define ROOT ((device_t)NULL) 155#define ROOT ((device_t)NULL)
156 156
157struct matchinfo { 157struct matchinfo {
158 cfsubmatch_t fn; 158 cfsubmatch_t fn;
159 device_t parent; 159 device_t parent;
160 const int *locs; 160 const int *locs;
161 void *aux; 161 void *aux;
162 struct cfdata *match; 162 struct cfdata *match;
163 int pri; 163 int pri;
164}; 164};
165 165
166struct alldevs_foray { 166struct alldevs_foray {
167 int af_s; 167 int af_s;
168 struct devicelist af_garbage; 168 struct devicelist af_garbage;
169}; 169};
170 170
171/* 171/*
172 * Internal version of the cfargs structure; all versions are 172 * Internal version of the cfargs structure; all versions are
173 * canonicalized to this. 173 * canonicalized to this.
174 */ 174 */
175struct cfargs_internal { 175struct cfargs_internal {
176 union { 176 union {
177 cfsubmatch_t submatch;/* submatch function (direct config) */ 177 cfsubmatch_t submatch;/* submatch function (direct config) */
178 cfsearch_t search; /* search function (indirect config) */ 178 cfsearch_t search; /* search function (indirect config) */
179 }; 179 };
180 const char * iattr; /* interface attribute */ 180 const char * iattr; /* interface attribute */
181 const int * locators; /* locators array */ 181 const int * locators; /* locators array */
182 devhandle_t devhandle; /* devhandle_t (by value) */ 182 devhandle_t devhandle; /* devhandle_t (by value) */
183}; 183};
184 184
185static char *number(char *, int); 185static char *number(char *, int);
186static void mapply(struct matchinfo *, cfdata_t); 186static void mapply(struct matchinfo *, cfdata_t);
187static void config_devdelete(device_t); 187static void config_devdelete(device_t);
188static void config_devunlink(device_t, struct devicelist *); 188static void config_devunlink(device_t, struct devicelist *);
189static void config_makeroom(int, struct cfdriver *); 189static void config_makeroom(int, struct cfdriver *);
190static void config_devlink(device_t); 190static void config_devlink(device_t);
191static void config_alldevs_enter(struct alldevs_foray *); 191static void config_alldevs_enter(struct alldevs_foray *);
192static void config_alldevs_exit(struct alldevs_foray *); 192static void config_alldevs_exit(struct alldevs_foray *);
193static void config_add_attrib_dict(device_t); 193static void config_add_attrib_dict(device_t);
194static device_t config_attach_internal(device_t, cfdata_t, void *, 194static device_t config_attach_internal(device_t, cfdata_t, void *,
195 cfprint_t, const struct cfargs_internal *); 195 cfprint_t, const struct cfargs_internal *);
196 196
197static void config_collect_garbage(struct devicelist *); 197static void config_collect_garbage(struct devicelist *);
198static void config_dump_garbage(struct devicelist *); 198static void config_dump_garbage(struct devicelist *);
199 199
200static void pmflock_debug(device_t, const char *, int); 200static void pmflock_debug(device_t, const char *, int);
201 201
202static device_t deviter_next1(deviter_t *); 202static device_t deviter_next1(deviter_t *);
203static void deviter_reinit(deviter_t *); 203static void deviter_reinit(deviter_t *);
204 204
205struct deferred_config { 205struct deferred_config {
206 TAILQ_ENTRY(deferred_config) dc_queue; 206 TAILQ_ENTRY(deferred_config) dc_queue;
207 device_t dc_dev; 207 device_t dc_dev;
208 void (*dc_func)(device_t); 208 void (*dc_func)(device_t);
209}; 209};
210 210
211TAILQ_HEAD(deferred_config_head, deferred_config); 211TAILQ_HEAD(deferred_config_head, deferred_config);
212 212
213static struct deferred_config_head deferred_config_queue = 213static struct deferred_config_head deferred_config_queue =
214 TAILQ_HEAD_INITIALIZER(deferred_config_queue); 214 TAILQ_HEAD_INITIALIZER(deferred_config_queue);
215static struct deferred_config_head interrupt_config_queue = 215static struct deferred_config_head interrupt_config_queue =
216 TAILQ_HEAD_INITIALIZER(interrupt_config_queue); 216 TAILQ_HEAD_INITIALIZER(interrupt_config_queue);
217static int interrupt_config_threads = 8; 217static int interrupt_config_threads = 8;
218static struct deferred_config_head mountroot_config_queue = 218static struct deferred_config_head mountroot_config_queue =
219 TAILQ_HEAD_INITIALIZER(mountroot_config_queue); 219 TAILQ_HEAD_INITIALIZER(mountroot_config_queue);
220static int mountroot_config_threads = 2; 220static int mountroot_config_threads = 2;
221static lwp_t **mountroot_config_lwpids; 221static lwp_t **mountroot_config_lwpids;
222static size_t mountroot_config_lwpids_size; 222static size_t mountroot_config_lwpids_size;
223bool root_is_mounted = false; 223bool root_is_mounted = false;
224 224
225static void config_process_deferred(struct deferred_config_head *, device_t); 225static void config_process_deferred(struct deferred_config_head *, device_t);
226 226
227/* Hooks to finalize configuration once all real devices have been found. */ 227/* Hooks to finalize configuration once all real devices have been found. */
228struct finalize_hook { 228struct finalize_hook {
229 TAILQ_ENTRY(finalize_hook) f_list; 229 TAILQ_ENTRY(finalize_hook) f_list;
230 int (*f_func)(device_t); 230 int (*f_func)(device_t);
231 device_t f_dev; 231 device_t f_dev;
232}; 232};
233static TAILQ_HEAD(, finalize_hook) config_finalize_list = 233static TAILQ_HEAD(, finalize_hook) config_finalize_list =
234 TAILQ_HEAD_INITIALIZER(config_finalize_list); 234 TAILQ_HEAD_INITIALIZER(config_finalize_list);
235static int config_finalize_done; 235static int config_finalize_done;
236 236
237/* list of all devices */ 237/* list of all devices */
238static struct devicelist alldevs = TAILQ_HEAD_INITIALIZER(alldevs); 238static struct devicelist alldevs = TAILQ_HEAD_INITIALIZER(alldevs);
239static kmutex_t alldevs_lock __cacheline_aligned; 239static kmutex_t alldevs_lock __cacheline_aligned;
240static devgen_t alldevs_gen = 1; 240static devgen_t alldevs_gen = 1;
241static int alldevs_nread = 0; 241static int alldevs_nread = 0;
242static int alldevs_nwrite = 0; 242static int alldevs_nwrite = 0;
243static bool alldevs_garbage = false; 243static bool alldevs_garbage = false;
244 244
245static struct devicelist config_pending = 245static struct devicelist config_pending =
246 TAILQ_HEAD_INITIALIZER(config_pending); 246 TAILQ_HEAD_INITIALIZER(config_pending);
247static kmutex_t config_misc_lock; 247static kmutex_t config_misc_lock;
248static kcondvar_t config_misc_cv; 248static kcondvar_t config_misc_cv;
249 249
250static bool detachall = false; 250static bool detachall = false;
251 251
252#define STREQ(s1, s2) \ 252#define STREQ(s1, s2) \
253 (*(s1) == *(s2) && strcmp((s1), (s2)) == 0) 253 (*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
254 254
255static bool config_initialized = false; /* config_init() has been called. */ 255static bool config_initialized = false; /* config_init() has been called. */
256 256
257static int config_do_twiddle; 257static int config_do_twiddle;
258static callout_t config_twiddle_ch; 258static callout_t config_twiddle_ch;
259 259
260static void sysctl_detach_setup(struct sysctllog **); 260static void sysctl_detach_setup(struct sysctllog **);
261 261
262int no_devmon_insert(const char *, prop_dictionary_t); 262int no_devmon_insert(const char *, prop_dictionary_t);
263int (*devmon_insert_vec)(const char *, prop_dictionary_t) = no_devmon_insert; 263int (*devmon_insert_vec)(const char *, prop_dictionary_t) = no_devmon_insert;
264 264
265typedef int (*cfdriver_fn)(struct cfdriver *); 265typedef int (*cfdriver_fn)(struct cfdriver *);
266static int 266static int
267frob_cfdrivervec(struct cfdriver * const *cfdriverv, 267frob_cfdrivervec(struct cfdriver * const *cfdriverv,
268 cfdriver_fn drv_do, cfdriver_fn drv_undo, 268 cfdriver_fn drv_do, cfdriver_fn drv_undo,
269 const char *style, bool dopanic) 269 const char *style, bool dopanic)
270{ 270{
271 void (*pr)(const char *, ...) __printflike(1, 2) = 271 void (*pr)(const char *, ...) __printflike(1, 2) =
272 dopanic ? panic : printf; 272 dopanic ? panic : printf;
273 int i, error = 0, e2 __diagused; 273 int i, error = 0, e2 __diagused;
274 274
275 for (i = 0; cfdriverv[i] != NULL; i++) { 275 for (i = 0; cfdriverv[i] != NULL; i++) {
276 if ((error = drv_do(cfdriverv[i])) != 0) { 276 if ((error = drv_do(cfdriverv[i])) != 0) {
277 pr("configure: `%s' driver %s failed: %d", 277 pr("configure: `%s' driver %s failed: %d",
278 cfdriverv[i]->cd_name, style, error); 278 cfdriverv[i]->cd_name, style, error);
279 goto bad; 279 goto bad;
280 } 280 }
281 } 281 }
282 282
283 KASSERT(error == 0); 283 KASSERT(error == 0);
284 return 0; 284 return 0;
285 285
286 bad: 286 bad:
287 printf("\n"); 287 printf("\n");
288 for (i--; i >= 0; i--) { 288 for (i--; i >= 0; i--) {
289 e2 = drv_undo(cfdriverv[i]); 289 e2 = drv_undo(cfdriverv[i]);
290 KASSERT(e2 == 0); 290 KASSERT(e2 == 0);
291 } 291 }
292 292
293 return error; 293 return error;
294} 294}
295 295
296typedef int (*cfattach_fn)(const char *, struct cfattach *); 296typedef int (*cfattach_fn)(const char *, struct cfattach *);
297static int 297static int
298frob_cfattachvec(const struct cfattachinit *cfattachv, 298frob_cfattachvec(const struct cfattachinit *cfattachv,
299 cfattach_fn att_do, cfattach_fn att_undo, 299 cfattach_fn att_do, cfattach_fn att_undo,
300 const char *style, bool dopanic) 300 const char *style, bool dopanic)
301{ 301{
302 const struct cfattachinit *cfai = NULL; 302 const struct cfattachinit *cfai = NULL;
303 void (*pr)(const char *, ...) __printflike(1, 2) = 303 void (*pr)(const char *, ...) __printflike(1, 2) =
304 dopanic ? panic : printf; 304 dopanic ? panic : printf;
305 int j = 0, error = 0, e2 __diagused; 305 int j = 0, error = 0, e2 __diagused;
306 306
307 for (cfai = &cfattachv[0]; cfai->cfai_name != NULL; cfai++) { 307 for (cfai = &cfattachv[0]; cfai->cfai_name != NULL; cfai++) {
308 for (j = 0; cfai->cfai_list[j] != NULL; j++) { 308 for (j = 0; cfai->cfai_list[j] != NULL; j++) {
309 if ((error = att_do(cfai->cfai_name, 309 if ((error = att_do(cfai->cfai_name,
310 cfai->cfai_list[j])) != 0) { 310 cfai->cfai_list[j])) != 0) {
311 pr("configure: attachment `%s' " 311 pr("configure: attachment `%s' "
312 "of `%s' driver %s failed: %d", 312 "of `%s' driver %s failed: %d",
313 cfai->cfai_list[j]->ca_name, 313 cfai->cfai_list[j]->ca_name,
314 cfai->cfai_name, style, error); 314 cfai->cfai_name, style, error);
315 goto bad; 315 goto bad;
316 } 316 }
317 } 317 }
318 } 318 }
319 319
320 KASSERT(error == 0); 320 KASSERT(error == 0);
321 return 0; 321 return 0;
322 322
323 bad: 323 bad:
324 /* 324 /*
325 * Rollback in reverse order. dunno if super-important, but 325 * Rollback in reverse order. dunno if super-important, but
326 * do that anyway. Although the code looks a little like 326 * do that anyway. Although the code looks a little like
327 * someone did a little integration (in the math sense). 327 * someone did a little integration (in the math sense).
328 */ 328 */
329 printf("\n"); 329 printf("\n");
330 if (cfai) { 330 if (cfai) {
331 bool last; 331 bool last;
332 332
333 for (last = false; last == false; ) { 333 for (last = false; last == false; ) {
334 if (cfai == &cfattachv[0]) 334 if (cfai == &cfattachv[0])
335 last = true; 335 last = true;
336 for (j--; j >= 0; j--) { 336 for (j--; j >= 0; j--) {
337 e2 = att_undo(cfai->cfai_name, 337 e2 = att_undo(cfai->cfai_name,
338 cfai->cfai_list[j]); 338 cfai->cfai_list[j]);
339 KASSERT(e2 == 0); 339 KASSERT(e2 == 0);
340 } 340 }
341 if (!last) { 341 if (!last) {
342 cfai--; 342 cfai--;
343 for (j = 0; cfai->cfai_list[j] != NULL; j++) 343 for (j = 0; cfai->cfai_list[j] != NULL; j++)
344 ; 344 ;
345 } 345 }
346 } 346 }
347 } 347 }
348 348
349 return error; 349 return error;
350} 350}
351 351
352/* 352/*
353 * Initialize the autoconfiguration data structures. Normally this 353 * Initialize the autoconfiguration data structures. Normally this
354 * is done by configure(), but some platforms need to do this very 354 * is done by configure(), but some platforms need to do this very
355 * early (to e.g. initialize the console). 355 * early (to e.g. initialize the console).
356 */ 356 */
357void 357void
358config_init(void) 358config_init(void)
359{ 359{
360 360
361 KASSERT(config_initialized == false); 361 KASSERT(config_initialized == false);
362 362
363 mutex_init(&alldevs_lock, MUTEX_DEFAULT, IPL_VM); 363 mutex_init(&alldevs_lock, MUTEX_DEFAULT, IPL_VM);
364 364
365 mutex_init(&config_misc_lock, MUTEX_DEFAULT, IPL_NONE); 365 mutex_init(&config_misc_lock, MUTEX_DEFAULT, IPL_NONE);
366 cv_init(&config_misc_cv, "cfgmisc"); 366 cv_init(&config_misc_cv, "cfgmisc");
367 367
368 callout_init(&config_twiddle_ch, CALLOUT_MPSAFE); 368 callout_init(&config_twiddle_ch, CALLOUT_MPSAFE);
369 369
370 frob_cfdrivervec(cfdriver_list_initial, 370 frob_cfdrivervec(cfdriver_list_initial,
371 config_cfdriver_attach, NULL, "bootstrap", true); 371 config_cfdriver_attach, NULL, "bootstrap", true);
372 frob_cfattachvec(cfattachinit, 372 frob_cfattachvec(cfattachinit,
373 config_cfattach_attach, NULL, "bootstrap", true); 373 config_cfattach_attach, NULL, "bootstrap", true);
374 374
375 initcftable.ct_cfdata = cfdata; 375 initcftable.ct_cfdata = cfdata;
376 TAILQ_INSERT_TAIL(&allcftables, &initcftable, ct_list); 376 TAILQ_INSERT_TAIL(&allcftables, &initcftable, ct_list);
377 377
378 rnd_attach_source(&rnd_autoconf_source, "autoconf", RND_TYPE_UNKNOWN, 378 rnd_attach_source(&rnd_autoconf_source, "autoconf", RND_TYPE_UNKNOWN,
379 RND_FLAG_COLLECT_TIME); 379 RND_FLAG_COLLECT_TIME);
380 380
381 config_initialized = true; 381 config_initialized = true;
382} 382}
383 383
384/* 384/*
385 * Init or fini drivers and attachments. Either all or none 385 * Init or fini drivers and attachments. Either all or none
386 * are processed (via rollback). It would be nice if this were 386 * are processed (via rollback). It would be nice if this were
387 * atomic to outside consumers, but with the current state of 387 * atomic to outside consumers, but with the current state of
388 * locking ... 388 * locking ...
389 */ 389 */
390int 390int
391config_init_component(struct cfdriver * const *cfdriverv, 391config_init_component(struct cfdriver * const *cfdriverv,
392 const struct cfattachinit *cfattachv, struct cfdata *cfdatav) 392 const struct cfattachinit *cfattachv, struct cfdata *cfdatav)
393{ 393{
394 int error; 394 int error;
395 395
396 KERNEL_LOCK(1, NULL); 396 KERNEL_LOCK(1, NULL);
397 397
398 if ((error = frob_cfdrivervec(cfdriverv, 398 if ((error = frob_cfdrivervec(cfdriverv,
399 config_cfdriver_attach, config_cfdriver_detach, "init", false))!= 0) 399 config_cfdriver_attach, config_cfdriver_detach, "init", false))!= 0)
400 goto out; 400 goto out;
401 if ((error = frob_cfattachvec(cfattachv, 401 if ((error = frob_cfattachvec(cfattachv,
402 config_cfattach_attach, config_cfattach_detach, 402 config_cfattach_attach, config_cfattach_detach,
403 "init", false)) != 0) { 403 "init", false)) != 0) {
404 frob_cfdrivervec(cfdriverv, 404 frob_cfdrivervec(cfdriverv,
405 config_cfdriver_detach, NULL, "init rollback", true); 405 config_cfdriver_detach, NULL, "init rollback", true);
406 goto out; 406 goto out;
407 } 407 }
408 if ((error = config_cfdata_attach(cfdatav, 1)) != 0) { 408 if ((error = config_cfdata_attach(cfdatav, 1)) != 0) {
409 frob_cfattachvec(cfattachv, 409 frob_cfattachvec(cfattachv,
410 config_cfattach_detach, NULL, "init rollback", true); 410 config_cfattach_detach, NULL, "init rollback", true);
411 frob_cfdrivervec(cfdriverv, 411 frob_cfdrivervec(cfdriverv,
412 config_cfdriver_detach, NULL, "init rollback", true); 412 config_cfdriver_detach, NULL, "init rollback", true);
413 goto out; 413 goto out;
414 } 414 }
415 415
416 /* Success! */ 416 /* Success! */
417 error = 0; 417 error = 0;
418 418
419out: KERNEL_UNLOCK_ONE(NULL); 419out: KERNEL_UNLOCK_ONE(NULL);
420 return error; 420 return error;
421} 421}
422 422
423int 423int
424config_fini_component(struct cfdriver * const *cfdriverv, 424config_fini_component(struct cfdriver * const *cfdriverv,
425 const struct cfattachinit *cfattachv, struct cfdata *cfdatav) 425 const struct cfattachinit *cfattachv, struct cfdata *cfdatav)
426{ 426{
427 int error; 427 int error;
428 428
429 KERNEL_LOCK(1, NULL); 429 KERNEL_LOCK(1, NULL);
430 430
431 if ((error = config_cfdata_detach(cfdatav)) != 0) 431 if ((error = config_cfdata_detach(cfdatav)) != 0)
432 goto out; 432 goto out;
433 if ((error = frob_cfattachvec(cfattachv, 433 if ((error = frob_cfattachvec(cfattachv,
434 config_cfattach_detach, config_cfattach_attach, 434 config_cfattach_detach, config_cfattach_attach,
435 "fini", false)) != 0) { 435 "fini", false)) != 0) {
436 if (config_cfdata_attach(cfdatav, 0) != 0) 436 if (config_cfdata_attach(cfdatav, 0) != 0)
437 panic("config_cfdata fini rollback failed"); 437 panic("config_cfdata fini rollback failed");
438 goto out; 438 goto out;
439 } 439 }
440 if ((error = frob_cfdrivervec(cfdriverv, 440 if ((error = frob_cfdrivervec(cfdriverv,
441 config_cfdriver_detach, config_cfdriver_attach, 441 config_cfdriver_detach, config_cfdriver_attach,
442 "fini", false)) != 0) { 442 "fini", false)) != 0) {
443 frob_cfattachvec(cfattachv, 443 frob_cfattachvec(cfattachv,
444 config_cfattach_attach, NULL, "fini rollback", true); 444 config_cfattach_attach, NULL, "fini rollback", true);
445 if (config_cfdata_attach(cfdatav, 0) != 0) 445 if (config_cfdata_attach(cfdatav, 0) != 0)
446 panic("config_cfdata fini rollback failed"); 446 panic("config_cfdata fini rollback failed");
447 goto out; 447 goto out;
448 } 448 }
449 449
450 /* Success! */ 450 /* Success! */
451 error = 0; 451 error = 0;
452 452
453out: KERNEL_UNLOCK_ONE(NULL); 453out: KERNEL_UNLOCK_ONE(NULL);
454 return error; 454 return error;
455} 455}
456 456
457void 457void
458config_init_mi(void) 458config_init_mi(void)
459{ 459{
460 460
461 if (!config_initialized) 461 if (!config_initialized)
462 config_init(); 462 config_init();
463 463
464 sysctl_detach_setup(NULL); 464 sysctl_detach_setup(NULL);
465} 465}
466 466
467void 467void
468config_deferred(device_t dev) 468config_deferred(device_t dev)
469{ 469{
470 470
471 KASSERT(KERNEL_LOCKED_P()); 471 KASSERT(KERNEL_LOCKED_P());
472 472
473 config_process_deferred(&deferred_config_queue, dev); 473 config_process_deferred(&deferred_config_queue, dev);
474 config_process_deferred(&interrupt_config_queue, dev); 474 config_process_deferred(&interrupt_config_queue, dev);
475 config_process_deferred(&mountroot_config_queue, dev); 475 config_process_deferred(&mountroot_config_queue, dev);
476} 476}
477 477
478static void 478static void
479config_interrupts_thread(void *cookie) 479config_interrupts_thread(void *cookie)
480{ 480{
481 struct deferred_config *dc; 481 struct deferred_config *dc;
482 device_t dev; 482 device_t dev;
483 483
484 mutex_enter(&config_misc_lock); 484 mutex_enter(&config_misc_lock);
485 while ((dc = TAILQ_FIRST(&interrupt_config_queue)) != NULL) { 485 while ((dc = TAILQ_FIRST(&interrupt_config_queue)) != NULL) {
486 TAILQ_REMOVE(&interrupt_config_queue, dc, dc_queue); 486 TAILQ_REMOVE(&interrupt_config_queue, dc, dc_queue);
487 mutex_exit(&config_misc_lock); 487 mutex_exit(&config_misc_lock);
488 488
489 dev = dc->dc_dev; 489 dev = dc->dc_dev;
490 (*dc->dc_func)(dev); 490 (*dc->dc_func)(dev);
491 if (!device_pmf_is_registered(dev)) 491 if (!device_pmf_is_registered(dev))
492 aprint_debug_dev(dev, 492 aprint_debug_dev(dev,
493 "WARNING: power management not supported\n"); 493 "WARNING: power management not supported\n");
494 config_pending_decr(dev); 494 config_pending_decr(dev);
495 kmem_free(dc, sizeof(*dc)); 495 kmem_free(dc, sizeof(*dc));
496 496
497 mutex_enter(&config_misc_lock); 497 mutex_enter(&config_misc_lock);
498 } 498 }
499 mutex_exit(&config_misc_lock); 499 mutex_exit(&config_misc_lock);
500 500
501 kthread_exit(0); 501 kthread_exit(0);
502} 502}
503 503
504void 504void
505config_create_interruptthreads(void) 505config_create_interruptthreads(void)
506{ 506{
507 int i; 507 int i;
508 508
509 for (i = 0; i < interrupt_config_threads; i++) { 509 for (i = 0; i < interrupt_config_threads; i++) {
510 (void)kthread_create(PRI_NONE, 0/*XXXSMP */, NULL, 510 (void)kthread_create(PRI_NONE, 0/*XXXSMP */, NULL,
511 config_interrupts_thread, NULL, NULL, "configintr"); 511 config_interrupts_thread, NULL, NULL, "configintr");
512 } 512 }
513} 513}
514 514
515static void 515static void
516config_mountroot_thread(void *cookie) 516config_mountroot_thread(void *cookie)
517{ 517{
518 struct deferred_config *dc; 518 struct deferred_config *dc;
519 519
520 mutex_enter(&config_misc_lock); 520 mutex_enter(&config_misc_lock);
521 while ((dc = TAILQ_FIRST(&mountroot_config_queue)) != NULL) { 521 while ((dc = TAILQ_FIRST(&mountroot_config_queue)) != NULL) {
522 TAILQ_REMOVE(&mountroot_config_queue, dc, dc_queue); 522 TAILQ_REMOVE(&mountroot_config_queue, dc, dc_queue);
523 mutex_exit(&config_misc_lock); 523 mutex_exit(&config_misc_lock);
524 524
525 (*dc->dc_func)(dc->dc_dev); 525 (*dc->dc_func)(dc->dc_dev);
526 kmem_free(dc, sizeof(*dc)); 526 kmem_free(dc, sizeof(*dc));
527 527
528 mutex_enter(&config_misc_lock); 528 mutex_enter(&config_misc_lock);
529 } 529 }
530 mutex_exit(&config_misc_lock); 530 mutex_exit(&config_misc_lock);
531 531
532 kthread_exit(0); 532 kthread_exit(0);
533} 533}
534 534
535void 535void
536config_create_mountrootthreads(void) 536config_create_mountrootthreads(void)
537{ 537{
538 int i; 538 int i;
539 539
540 if (!root_is_mounted) 540 if (!root_is_mounted)
541 root_is_mounted = true; 541 root_is_mounted = true;
542 542
543 mountroot_config_lwpids_size = sizeof(mountroot_config_lwpids) * 543 mountroot_config_lwpids_size = sizeof(mountroot_config_lwpids) *
544 mountroot_config_threads; 544 mountroot_config_threads;
545 mountroot_config_lwpids = kmem_alloc(mountroot_config_lwpids_size, 545 mountroot_config_lwpids = kmem_alloc(mountroot_config_lwpids_size,
546 KM_NOSLEEP); 546 KM_NOSLEEP);
547 KASSERT(mountroot_config_lwpids); 547 KASSERT(mountroot_config_lwpids);
548 for (i = 0; i < mountroot_config_threads; i++) { 548 for (i = 0; i < mountroot_config_threads; i++) {
549 mountroot_config_lwpids[i] = 0; 549 mountroot_config_lwpids[i] = 0;
550 (void)kthread_create(PRI_NONE, KTHREAD_MUSTJOIN/* XXXSMP */, 550 (void)kthread_create(PRI_NONE, KTHREAD_MUSTJOIN/* XXXSMP */,
551 NULL, config_mountroot_thread, NULL, 551 NULL, config_mountroot_thread, NULL,
552 &mountroot_config_lwpids[i], 552 &mountroot_config_lwpids[i],
553 "configroot"); 553 "configroot");
554 } 554 }
555} 555}
556 556
557void 557void
558config_finalize_mountroot(void) 558config_finalize_mountroot(void)
559{ 559{
560 int i, error; 560 int i, error;
561 561
562 for (i = 0; i < mountroot_config_threads; i++) { 562 for (i = 0; i < mountroot_config_threads; i++) {
563 if (mountroot_config_lwpids[i] == 0) 563 if (mountroot_config_lwpids[i] == 0)
564 continue; 564 continue;
565 565
566 error = kthread_join(mountroot_config_lwpids[i]); 566 error = kthread_join(mountroot_config_lwpids[i]);
567 if (error) 567 if (error)
568 printf("%s: thread %x joined with error %d\n", 568 printf("%s: thread %x joined with error %d\n",
569 __func__, i, error); 569 __func__, i, error);
570 } 570 }
571 kmem_free(mountroot_config_lwpids, mountroot_config_lwpids_size); 571 kmem_free(mountroot_config_lwpids, mountroot_config_lwpids_size);
572} 572}
573 573
574/* 574/*
575 * Announce device attach/detach to userland listeners. 575 * Announce device attach/detach to userland listeners.
576 */ 576 */
577 577
578int 578int
579no_devmon_insert(const char *name, prop_dictionary_t p) 579no_devmon_insert(const char *name, prop_dictionary_t p)
580{ 580{
581 581
582 return ENODEV; 582 return ENODEV;
583} 583}
584 584
585static void 585static void
586devmon_report_device(device_t dev, bool isattach) 586devmon_report_device(device_t dev, bool isattach)
587{ 587{
588 prop_dictionary_t ev, dict = device_properties(dev); 588 prop_dictionary_t ev, dict = device_properties(dev);
589 const char *parent; 589 const char *parent;
590 const char *what; 590 const char *what;
591 const char *where; 591 const char *where;
592 device_t pdev = device_parent(dev); 592 device_t pdev = device_parent(dev);
593 593
594 /* If currently no drvctl device, just return */ 594 /* If currently no drvctl device, just return */
595 if (devmon_insert_vec == no_devmon_insert) 595 if (devmon_insert_vec == no_devmon_insert)
596 return; 596 return;
597 597
598 ev = prop_dictionary_create(); 598 ev = prop_dictionary_create();
599 if (ev == NULL) 599 if (ev == NULL)
600 return; 600 return;
601 601
602 what = (isattach ? "device-attach" : "device-detach"); 602 what = (isattach ? "device-attach" : "device-detach");
603 parent = (pdev == NULL ? "root" : device_xname(pdev)); 603 parent = (pdev == NULL ? "root" : device_xname(pdev));
604 if (prop_dictionary_get_string(dict, "location", &where)) { 604 if (prop_dictionary_get_string(dict, "location", &where)) {
605 prop_dictionary_set_string(ev, "location", where); 605 prop_dictionary_set_string(ev, "location", where);
606 aprint_debug("ev: %s %s at %s in [%s]\n", 606 aprint_debug("ev: %s %s at %s in [%s]\n",
607 what, device_xname(dev), parent, where);  607 what, device_xname(dev), parent, where);
608 } 608 }
609 if (!prop_dictionary_set_string(ev, "device", device_xname(dev)) || 609 if (!prop_dictionary_set_string(ev, "device", device_xname(dev)) ||
610 !prop_dictionary_set_string(ev, "parent", parent)) { 610 !prop_dictionary_set_string(ev, "parent", parent)) {
611 prop_object_release(ev); 611 prop_object_release(ev);
612 return; 612 return;
613 } 613 }
614 614
615 if ((*devmon_insert_vec)(what, ev) != 0) 615 if ((*devmon_insert_vec)(what, ev) != 0)
616 prop_object_release(ev); 616 prop_object_release(ev);
617} 617}
618 618
619/* 619/*
620 * Add a cfdriver to the system. 620 * Add a cfdriver to the system.
621 */ 621 */
622int 622int
623config_cfdriver_attach(struct cfdriver *cd) 623config_cfdriver_attach(struct cfdriver *cd)
624{ 624{
625 struct cfdriver *lcd; 625 struct cfdriver *lcd;
626 626
627 /* Make sure this driver isn't already in the system. */ 627 /* Make sure this driver isn't already in the system. */
628 LIST_FOREACH(lcd, &allcfdrivers, cd_list) { 628 LIST_FOREACH(lcd, &allcfdrivers, cd_list) {
629 if (STREQ(lcd->cd_name, cd->cd_name)) 629 if (STREQ(lcd->cd_name, cd->cd_name))
630 return EEXIST; 630 return EEXIST;
631 } 631 }
632 632
633 LIST_INIT(&cd->cd_attach); 633 LIST_INIT(&cd->cd_attach);
634 LIST_INSERT_HEAD(&allcfdrivers, cd, cd_list); 634 LIST_INSERT_HEAD(&allcfdrivers, cd, cd_list);
635 635
636 return 0; 636 return 0;
637} 637}
638 638
639/* 639/*
640 * Remove a cfdriver from the system. 640 * Remove a cfdriver from the system.
641 */ 641 */
642int 642int
643config_cfdriver_detach(struct cfdriver *cd) 643config_cfdriver_detach(struct cfdriver *cd)
644{ 644{
645 struct alldevs_foray af; 645 struct alldevs_foray af;
646 int i, rc = 0; 646 int i, rc = 0;
647 647
648 config_alldevs_enter(&af); 648 config_alldevs_enter(&af);
649 /* Make sure there are no active instances. */ 649 /* Make sure there are no active instances. */
650 for (i = 0; i < cd->cd_ndevs; i++) { 650 for (i = 0; i < cd->cd_ndevs; i++) {
651 if (cd->cd_devs[i] != NULL) { 651 if (cd->cd_devs[i] != NULL) {
652 rc = EBUSY; 652 rc = EBUSY;
653 break; 653 break;
654 } 654 }
655 } 655 }
656 config_alldevs_exit(&af); 656 config_alldevs_exit(&af);
657 657
658 if (rc != 0) 658 if (rc != 0)
659 return rc; 659 return rc;
660 660
661 /* ...and no attachments loaded. */ 661 /* ...and no attachments loaded. */
662 if (LIST_EMPTY(&cd->cd_attach) == 0) 662 if (LIST_EMPTY(&cd->cd_attach) == 0)
663 return EBUSY; 663 return EBUSY;
664 664
665 LIST_REMOVE(cd, cd_list); 665 LIST_REMOVE(cd, cd_list);
666 666
667 KASSERT(cd->cd_devs == NULL); 667 KASSERT(cd->cd_devs == NULL);
668 668
669 return 0; 669 return 0;
670} 670}
671 671
672/* 672/*
673 * Look up a cfdriver by name. 673 * Look up a cfdriver by name.
674 */ 674 */
675struct cfdriver * 675struct cfdriver *
676config_cfdriver_lookup(const char *name) 676config_cfdriver_lookup(const char *name)
677{ 677{
678 struct cfdriver *cd; 678 struct cfdriver *cd;
679 679
680 LIST_FOREACH(cd, &allcfdrivers, cd_list) { 680 LIST_FOREACH(cd, &allcfdrivers, cd_list) {
681 if (STREQ(cd->cd_name, name)) 681 if (STREQ(cd->cd_name, name))
682 return cd; 682 return cd;
683 } 683 }
684 684
685 return NULL; 685 return NULL;
686} 686}
687 687
688/* 688/*
689 * Add a cfattach to the specified driver. 689 * Add a cfattach to the specified driver.
690 */ 690 */
691int 691int
692config_cfattach_attach(const char *driver, struct cfattach *ca) 692config_cfattach_attach(const char *driver, struct cfattach *ca)
693{ 693{
694 struct cfattach *lca; 694 struct cfattach *lca;
695 struct cfdriver *cd; 695 struct cfdriver *cd;
696 696
697 cd = config_cfdriver_lookup(driver); 697 cd = config_cfdriver_lookup(driver);
698 if (cd == NULL) 698 if (cd == NULL)
699 return ESRCH; 699 return ESRCH;
700 700
701 /* Make sure this attachment isn't already on this driver. */ 701 /* Make sure this attachment isn't already on this driver. */
702 LIST_FOREACH(lca, &cd->cd_attach, ca_list) { 702 LIST_FOREACH(lca, &cd->cd_attach, ca_list) {
703 if (STREQ(lca->ca_name, ca->ca_name)) 703 if (STREQ(lca->ca_name, ca->ca_name))
704 return EEXIST; 704 return EEXIST;
705 } 705 }
706 706
707 LIST_INSERT_HEAD(&cd->cd_attach, ca, ca_list); 707 LIST_INSERT_HEAD(&cd->cd_attach, ca, ca_list);
708 708
709 return 0; 709 return 0;
710} 710}
711 711
712/* 712/*
713 * Remove a cfattach from the specified driver. 713 * Remove a cfattach from the specified driver.
714 */ 714 */
715int 715int
716config_cfattach_detach(const char *driver, struct cfattach *ca) 716config_cfattach_detach(const char *driver, struct cfattach *ca)
717{ 717{
718 struct alldevs_foray af; 718 struct alldevs_foray af;
719 struct cfdriver *cd; 719 struct cfdriver *cd;
720 device_t dev; 720 device_t dev;
721 int i, rc = 0; 721 int i, rc = 0;
722 722
723 cd = config_cfdriver_lookup(driver); 723 cd = config_cfdriver_lookup(driver);
724 if (cd == NULL) 724 if (cd == NULL)
725 return ESRCH; 725 return ESRCH;
726 726
727 config_alldevs_enter(&af); 727 config_alldevs_enter(&af);
728 /* Make sure there are no active instances. */ 728 /* Make sure there are no active instances. */
729 for (i = 0; i < cd->cd_ndevs; i++) { 729 for (i = 0; i < cd->cd_ndevs; i++) {
730 if ((dev = cd->cd_devs[i]) == NULL) 730 if ((dev = cd->cd_devs[i]) == NULL)
731 continue; 731 continue;
732 if (dev->dv_cfattach == ca) { 732 if (dev->dv_cfattach == ca) {
733 rc = EBUSY; 733 rc = EBUSY;
734 break; 734 break;
735 } 735 }
736 } 736 }
737 config_alldevs_exit(&af); 737 config_alldevs_exit(&af);
738 738
739 if (rc != 0) 739 if (rc != 0)
740 return rc; 740 return rc;
741 741
742 LIST_REMOVE(ca, ca_list); 742 LIST_REMOVE(ca, ca_list);
743 743
744 return 0; 744 return 0;
745} 745}
746 746
747/* 747/*
748 * Look up a cfattach by name. 748 * Look up a cfattach by name.
749 */ 749 */
750static struct cfattach * 750static struct cfattach *
751config_cfattach_lookup_cd(struct cfdriver *cd, const char *atname) 751config_cfattach_lookup_cd(struct cfdriver *cd, const char *atname)
752{ 752{
753 struct cfattach *ca; 753 struct cfattach *ca;
754 754
755 LIST_FOREACH(ca, &cd->cd_attach, ca_list) { 755 LIST_FOREACH(ca, &cd->cd_attach, ca_list) {
756 if (STREQ(ca->ca_name, atname)) 756 if (STREQ(ca->ca_name, atname))
757 return ca; 757 return ca;
758 } 758 }
759 759
760 return NULL; 760 return NULL;
761} 761}
762 762
763/* 763/*
764 * Look up a cfattach by driver/attachment name. 764 * Look up a cfattach by driver/attachment name.
765 */ 765 */
766struct cfattach * 766struct cfattach *
767config_cfattach_lookup(const char *name, const char *atname) 767config_cfattach_lookup(const char *name, const char *atname)
768{ 768{
769 struct cfdriver *cd; 769 struct cfdriver *cd;
770 770
771 cd = config_cfdriver_lookup(name); 771 cd = config_cfdriver_lookup(name);
772 if (cd == NULL) 772 if (cd == NULL)
773 return NULL; 773 return NULL;
774 774
775 return config_cfattach_lookup_cd(cd, atname); 775 return config_cfattach_lookup_cd(cd, atname);
776} 776}
777 777
778/* 778/*
779 * Apply the matching function and choose the best. This is used 779 * Apply the matching function and choose the best. This is used
780 * a few times and we want to keep the code small. 780 * a few times and we want to keep the code small.
781 */ 781 */
782static void 782static void
783mapply(struct matchinfo *m, cfdata_t cf) 783mapply(struct matchinfo *m, cfdata_t cf)
784{ 784{
785 int pri; 785 int pri;
786 786
787 if (m->fn != NULL) { 787 if (m->fn != NULL) {
788 pri = (*m->fn)(m->parent, cf, m->locs, m->aux); 788 pri = (*m->fn)(m->parent, cf, m->locs, m->aux);
789 } else { 789 } else {
790 pri = config_match(m->parent, cf, m->aux); 790 pri = config_match(m->parent, cf, m->aux);
791 } 791 }
792 if (pri > m->pri) { 792 if (pri > m->pri) {
793 m->match = cf; 793 m->match = cf;
794 m->pri = pri; 794 m->pri = pri;
795 } 795 }
796} 796}
797 797
798int 798int
799config_stdsubmatch(device_t parent, cfdata_t cf, const int *locs, void *aux) 799config_stdsubmatch(device_t parent, cfdata_t cf, const int *locs, void *aux)
800{ 800{
801 const struct cfiattrdata *ci; 801 const struct cfiattrdata *ci;
802 const struct cflocdesc *cl; 802 const struct cflocdesc *cl;
803 int nlocs, i; 803 int nlocs, i;
804 804
805 ci = cfiattr_lookup(cfdata_ifattr(cf), parent->dv_cfdriver); 805 ci = cfiattr_lookup(cfdata_ifattr(cf), parent->dv_cfdriver);
806 KASSERT(ci); 806 KASSERT(ci);
807 nlocs = ci->ci_loclen; 807 nlocs = ci->ci_loclen;
808 KASSERT(!nlocs || locs); 808 KASSERT(!nlocs || locs);
809 for (i = 0; i < nlocs; i++) { 809 for (i = 0; i < nlocs; i++) {
810 cl = &ci->ci_locdesc[i]; 810 cl = &ci->ci_locdesc[i];
811 if (cl->cld_defaultstr != NULL && 811 if (cl->cld_defaultstr != NULL &&
812 cf->cf_loc[i] == cl->cld_default) 812 cf->cf_loc[i] == cl->cld_default)
813 continue; 813 continue;
814 if (cf->cf_loc[i] == locs[i]) 814 if (cf->cf_loc[i] == locs[i])
815 continue; 815 continue;
816 return 0; 816 return 0;
817 } 817 }
818 818
819 return config_match(parent, cf, aux); 819 return config_match(parent, cf, aux);
820} 820}
821 821
822/* 822/*
823 * Helper function: check whether the driver supports the interface attribute 823 * Helper function: check whether the driver supports the interface attribute
824 * and return its descriptor structure. 824 * and return its descriptor structure.
825 */ 825 */
826static const struct cfiattrdata * 826static const struct cfiattrdata *
827cfdriver_get_iattr(const struct cfdriver *cd, const char *ia) 827cfdriver_get_iattr(const struct cfdriver *cd, const char *ia)
828{ 828{
829 const struct cfiattrdata * const *cpp; 829 const struct cfiattrdata * const *cpp;
830 830
831 if (cd->cd_attrs == NULL) 831 if (cd->cd_attrs == NULL)
832 return 0; 832 return 0;
833 833
834 for (cpp = cd->cd_attrs; *cpp; cpp++) { 834 for (cpp = cd->cd_attrs; *cpp; cpp++) {
835 if (STREQ((*cpp)->ci_name, ia)) { 835 if (STREQ((*cpp)->ci_name, ia)) {
836 /* Match. */ 836 /* Match. */
837 return *cpp; 837 return *cpp;
838 } 838 }
839 } 839 }
840 return 0; 840 return 0;
841} 841}
842 842
843static int __diagused 843static int __diagused
844cfdriver_iattr_count(const struct cfdriver *cd) 844cfdriver_iattr_count(const struct cfdriver *cd)
845{ 845{
846 const struct cfiattrdata * const *cpp; 846 const struct cfiattrdata * const *cpp;
847 int i; 847 int i;
848 848
849 if (cd->cd_attrs == NULL) 849 if (cd->cd_attrs == NULL)
850 return 0; 850 return 0;
851 851
852 for (i = 0, cpp = cd->cd_attrs; *cpp; cpp++) { 852 for (i = 0, cpp = cd->cd_attrs; *cpp; cpp++) {
853 i++; 853 i++;
854 } 854 }
855 return i; 855 return i;
856} 856}
857 857
858/* 858/*
859 * Lookup an interface attribute description by name. 859 * Lookup an interface attribute description by name.
860 * If the driver is given, consider only its supported attributes. 860 * If the driver is given, consider only its supported attributes.
861 */ 861 */
862const struct cfiattrdata * 862const struct cfiattrdata *
863cfiattr_lookup(const char *name, const struct cfdriver *cd) 863cfiattr_lookup(const char *name, const struct cfdriver *cd)
864{ 864{
865 const struct cfdriver *d; 865 const struct cfdriver *d;
866 const struct cfiattrdata *ia; 866 const struct cfiattrdata *ia;
867 867
868 if (cd) 868 if (cd)
869 return cfdriver_get_iattr(cd, name); 869 return cfdriver_get_iattr(cd, name);
870 870
871 LIST_FOREACH(d, &allcfdrivers, cd_list) { 871 LIST_FOREACH(d, &allcfdrivers, cd_list) {
872 ia = cfdriver_get_iattr(d, name); 872 ia = cfdriver_get_iattr(d, name);
873 if (ia) 873 if (ia)
874 return ia; 874 return ia;
875 } 875 }
876 return 0; 876 return 0;
877} 877}
878 878
879/* 879/*
880 * Determine if `parent' is a potential parent for a device spec based 880 * Determine if `parent' is a potential parent for a device spec based
881 * on `cfp'. 881 * on `cfp'.
882 */ 882 */
883static int 883static int
884cfparent_match(const device_t parent, const struct cfparent *cfp) 884cfparent_match(const device_t parent, const struct cfparent *cfp)
885{ 885{
886 struct cfdriver *pcd; 886 struct cfdriver *pcd;
887 887
888 /* We don't match root nodes here. */ 888 /* We don't match root nodes here. */
889 if (cfp == NULL) 889 if (cfp == NULL)
890 return 0; 890 return 0;
891 891
892 pcd = parent->dv_cfdriver; 892 pcd = parent->dv_cfdriver;
893 KASSERT(pcd != NULL); 893 KASSERT(pcd != NULL);
894 894
895 /* 895 /*
896 * First, ensure this parent has the correct interface 896 * First, ensure this parent has the correct interface
897 * attribute. 897 * attribute.
898 */ 898 */
899 if (!cfdriver_get_iattr(pcd, cfp->cfp_iattr)) 899 if (!cfdriver_get_iattr(pcd, cfp->cfp_iattr))
900 return 0; 900 return 0;
901 901
902 /* 902 /*
903 * If no specific parent device instance was specified (i.e. 903 * If no specific parent device instance was specified (i.e.
904 * we're attaching to the attribute only), we're done! 904 * we're attaching to the attribute only), we're done!
905 */ 905 */
906 if (cfp->cfp_parent == NULL) 906 if (cfp->cfp_parent == NULL)
907 return 1; 907 return 1;
908 908
909 /* 909 /*
910 * Check the parent device's name. 910 * Check the parent device's name.
911 */ 911 */
912 if (STREQ(pcd->cd_name, cfp->cfp_parent) == 0) 912 if (STREQ(pcd->cd_name, cfp->cfp_parent) == 0)
913 return 0; /* not the same parent */ 913 return 0; /* not the same parent */
914 914
915 /* 915 /*
916 * Make sure the unit number matches. 916 * Make sure the unit number matches.
917 */ 917 */
918 if (cfp->cfp_unit == DVUNIT_ANY || /* wildcard */ 918 if (cfp->cfp_unit == DVUNIT_ANY || /* wildcard */
919 cfp->cfp_unit == parent->dv_unit) 919 cfp->cfp_unit == parent->dv_unit)
920 return 1; 920 return 1;
921 921
922 /* Unit numbers don't match. */ 922 /* Unit numbers don't match. */
923 return 0; 923 return 0;
924} 924}
925 925
926/* 926/*
927 * Helper for config_cfdata_attach(): check all devices whether it could be 927 * Helper for config_cfdata_attach(): check all devices whether it could be
928 * parent any attachment in the config data table passed, and rescan. 928 * parent any attachment in the config data table passed, and rescan.
929 */ 929 */
930static void 930static void
931rescan_with_cfdata(const struct cfdata *cf) 931rescan_with_cfdata(const struct cfdata *cf)
932{ 932{
933 device_t d; 933 device_t d;
934 const struct cfdata *cf1; 934 const struct cfdata *cf1;
935 deviter_t di; 935 deviter_t di;
936 936
937 KASSERT(KERNEL_LOCKED_P()); 937 KASSERT(KERNEL_LOCKED_P());
938 938
939 /* 939 /*
940 * "alldevs" is likely longer than a modules's cfdata, so make it 940 * "alldevs" is likely longer than a modules's cfdata, so make it
941 * the outer loop. 941 * the outer loop.
942 */ 942 */
943 for (d = deviter_first(&di, 0); d != NULL; d = deviter_next(&di)) { 943 for (d = deviter_first(&di, 0); d != NULL; d = deviter_next(&di)) {
944 944
945 if (!(d->dv_cfattach->ca_rescan)) 945 if (!(d->dv_cfattach->ca_rescan))
946 continue; 946 continue;
947 947
948 for (cf1 = cf; cf1->cf_name; cf1++) { 948 for (cf1 = cf; cf1->cf_name; cf1++) {
949 949
950 if (!cfparent_match(d, cf1->cf_pspec)) 950 if (!cfparent_match(d, cf1->cf_pspec))
951 continue; 951 continue;
952 952
953 (*d->dv_cfattach->ca_rescan)(d, 953 (*d->dv_cfattach->ca_rescan)(d,
954 cfdata_ifattr(cf1), cf1->cf_loc); 954 cfdata_ifattr(cf1), cf1->cf_loc);
955 955
956 config_deferred(d); 956 config_deferred(d);
957 } 957 }
958 } 958 }
959 deviter_release(&di); 959 deviter_release(&di);
960} 960}
961 961
962/* 962/*
963 * Attach a supplemental config data table and rescan potential 963 * Attach a supplemental config data table and rescan potential
964 * parent devices if required. 964 * parent devices if required.
965 */ 965 */
966int 966int
967config_cfdata_attach(cfdata_t cf, int scannow) 967config_cfdata_attach(cfdata_t cf, int scannow)
968{ 968{
969 struct cftable *ct; 969 struct cftable *ct;
970 970
971 KERNEL_LOCK(1, NULL); 971 KERNEL_LOCK(1, NULL);
972 972
973 ct = kmem_alloc(sizeof(*ct), KM_SLEEP); 973 ct = kmem_alloc(sizeof(*ct), KM_SLEEP);
974 ct->ct_cfdata = cf; 974 ct->ct_cfdata = cf;
975 TAILQ_INSERT_TAIL(&allcftables, ct, ct_list); 975 TAILQ_INSERT_TAIL(&allcftables, ct, ct_list);
976 976
977 if (scannow) 977 if (scannow)
978 rescan_with_cfdata(cf); 978 rescan_with_cfdata(cf);
979 979
980 KERNEL_UNLOCK_ONE(NULL); 980 KERNEL_UNLOCK_ONE(NULL);
981 981
982 return 0; 982 return 0;
983} 983}
984 984
985/* 985/*
986 * Helper for config_cfdata_detach: check whether a device is 986 * Helper for config_cfdata_detach: check whether a device is
987 * found through any attachment in the config data table. 987 * found through any attachment in the config data table.
988 */ 988 */
989static int 989static int
990dev_in_cfdata(device_t d, cfdata_t cf) 990dev_in_cfdata(device_t d, cfdata_t cf)
991{ 991{
992 const struct cfdata *cf1; 992 const struct cfdata *cf1;
993 993
994 for (cf1 = cf; cf1->cf_name; cf1++) 994 for (cf1 = cf; cf1->cf_name; cf1++)
995 if (d->dv_cfdata == cf1) 995 if (d->dv_cfdata == cf1)
996 return 1; 996 return 1;
997 997
998 return 0; 998 return 0;
999} 999}
1000 1000
1001/* 1001/*
1002 * Detach a supplemental config data table. Detach all devices found 1002 * Detach a supplemental config data table. Detach all devices found
1003 * through that table (and thus keeping references to it) before. 1003 * through that table (and thus keeping references to it) before.
1004 */ 1004 */
1005int 1005int
1006config_cfdata_detach(cfdata_t cf) 1006config_cfdata_detach(cfdata_t cf)
1007{ 1007{
1008 device_t d; 1008 device_t d;
1009 int error = 0; 1009 int error = 0;
1010 struct cftable *ct; 1010 struct cftable *ct;
1011 deviter_t di; 1011 deviter_t di;
1012 1012
1013 KERNEL_LOCK(1, NULL); 1013 KERNEL_LOCK(1, NULL);
1014 1014
1015 for (d = deviter_first(&di, DEVITER_F_RW); d != NULL; 1015 for (d = deviter_first(&di, DEVITER_F_RW); d != NULL;
1016 d = deviter_next(&di)) { 1016 d = deviter_next(&di)) {
1017 if (!dev_in_cfdata(d, cf)) 1017 if (!dev_in_cfdata(d, cf))
1018 continue; 1018 continue;
1019 if ((error = config_detach(d, 0)) != 0) 1019 if ((error = config_detach(d, 0)) != 0)
1020 break; 1020 break;
1021 } 1021 }
1022 deviter_release(&di); 1022 deviter_release(&di);
1023 if (error) { 1023 if (error) {
1024 aprint_error_dev(d, "unable to detach instance\n"); 1024 aprint_error_dev(d, "unable to detach instance\n");
1025 goto out; 1025 goto out;
1026 } 1026 }
1027 1027
1028 TAILQ_FOREACH(ct, &allcftables, ct_list) { 1028 TAILQ_FOREACH(ct, &allcftables, ct_list) {
1029 if (ct->ct_cfdata == cf) { 1029 if (ct->ct_cfdata == cf) {
1030 TAILQ_REMOVE(&allcftables, ct, ct_list); 1030 TAILQ_REMOVE(&allcftables, ct, ct_list);
1031 kmem_free(ct, sizeof(*ct)); 1031 kmem_free(ct, sizeof(*ct));
1032 error = 0; 1032 error = 0;
1033 goto out; 1033 goto out;
1034 } 1034 }
1035 } 1035 }
1036 1036
1037 /* not found -- shouldn't happen */ 1037 /* not found -- shouldn't happen */
1038 error = EINVAL; 1038 error = EINVAL;
1039 1039
1040out: KERNEL_UNLOCK_ONE(NULL); 1040out: KERNEL_UNLOCK_ONE(NULL);
1041 return error; 1041 return error;
1042} 1042}
1043 1043
1044/* 1044/*
1045 * Invoke the "match" routine for a cfdata entry on behalf of 1045 * Invoke the "match" routine for a cfdata entry on behalf of
1046 * an external caller, usually a direct config "submatch" routine. 1046 * an external caller, usually a direct config "submatch" routine.
1047 */ 1047 */
1048int 1048int
1049config_match(device_t parent, cfdata_t cf, void *aux) 1049config_match(device_t parent, cfdata_t cf, void *aux)
1050{ 1050{
1051 struct cfattach *ca; 1051 struct cfattach *ca;
1052 1052
1053 KASSERT(KERNEL_LOCKED_P()); 1053 KASSERT(KERNEL_LOCKED_P());
1054 1054
1055 ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname); 1055 ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname);
1056 if (ca == NULL) { 1056 if (ca == NULL) {
1057 /* No attachment for this entry, oh well. */ 1057 /* No attachment for this entry, oh well. */
1058 return 0; 1058 return 0;
1059 } 1059 }
1060 1060
1061 return (*ca->ca_match)(parent, cf, aux); 1061 return (*ca->ca_match)(parent, cf, aux);
1062} 1062}
1063 1063
1064/* 1064/*
1065 * Invoke the "probe" routine for a cfdata entry on behalf of 1065 * Invoke the "probe" routine for a cfdata entry on behalf of
1066 * an external caller, usually an indirect config "search" routine. 1066 * an external caller, usually an indirect config "search" routine.
1067 */ 1067 */
1068int 1068int
1069config_probe(device_t parent, cfdata_t cf, void *aux) 1069config_probe(device_t parent, cfdata_t cf, void *aux)
1070{ 1070{
1071 /* 1071 /*
1072 * This is currently a synonym for config_match(), but this 1072 * This is currently a synonym for config_match(), but this
1073 * is an implementation detail; "match" and "probe" routines 1073 * is an implementation detail; "match" and "probe" routines
1074 * have different behaviors. 1074 * have different behaviors.
1075 * 1075 *
1076 * XXX config_probe() should return a bool, because there is 1076 * XXX config_probe() should return a bool, because there is
1077 * XXX no match score for probe -- it's either there or it's 1077 * XXX no match score for probe -- it's either there or it's
1078 * XXX not, but some ports abuse the return value as a way 1078 * XXX not, but some ports abuse the return value as a way
1079 * XXX to attach "critical" devices before "non-critical" 1079 * XXX to attach "critical" devices before "non-critical"
1080 * XXX devices. 1080 * XXX devices.
1081 */ 1081 */
1082 return config_match(parent, cf, aux); 1082 return config_match(parent, cf, aux);
1083} 1083}
1084 1084
1085static struct cfargs_internal * 1085static struct cfargs_internal *
1086cfargs_canonicalize(const struct cfargs * const cfargs, 1086cfargs_canonicalize(const struct cfargs * const cfargs,
1087 struct cfargs_internal * const store) 1087 struct cfargs_internal * const store)
1088{ 1088{
1089 struct cfargs_internal *args = store; 1089 struct cfargs_internal *args = store;
1090 1090
1091 memset(args, 0, sizeof(*args)); 1091 memset(args, 0, sizeof(*args));
1092 1092
1093 /* If none specified, are all-NULL pointers are good. */ 1093 /* If none specified, are all-NULL pointers are good. */
1094 if (cfargs == NULL) { 1094 if (cfargs == NULL) {
1095 return args; 1095 return args;
1096 } 1096 }
1097 1097
1098 /* 1098 /*
1099 * Only one arguments version is recognized at this time. 1099 * Only one arguments version is recognized at this time.
1100 */ 1100 */
1101 if (cfargs->cfargs_version != CFARGS_VERSION) { 1101 if (cfargs->cfargs_version != CFARGS_VERSION) {
1102 panic("cfargs_canonicalize: unknown version %lu\n", 1102 panic("cfargs_canonicalize: unknown version %lu\n",
1103 (unsigned long)cfargs->cfargs_version); 1103 (unsigned long)cfargs->cfargs_version);
1104 } 1104 }
1105 1105
1106 /* 1106 /*
1107 * submatch and search are mutually-exclusive. 1107 * submatch and search are mutually-exclusive.
1108 */ 1108 */
1109 if (cfargs->submatch != NULL && cfargs->search != NULL) { 1109 if (cfargs->submatch != NULL && cfargs->search != NULL) {
1110 panic("cfargs_canonicalize: submatch and search are " 1110 panic("cfargs_canonicalize: submatch and search are "
1111 "mutually-exclusive"); 1111 "mutually-exclusive");
1112 } 1112 }
1113 if (cfargs->submatch != NULL) { 1113 if (cfargs->submatch != NULL) {
1114 args->submatch = cfargs->submatch; 1114 args->submatch = cfargs->submatch;
1115 } else if (cfargs->search != NULL) { 1115 } else if (cfargs->search != NULL) {
1116 args->search = cfargs->search; 1116 args->search = cfargs->search;
1117 } 1117 }
1118 1118
1119 args->iattr = cfargs->iattr; 1119 args->iattr = cfargs->iattr;
1120 args->locators = cfargs->locators; 1120 args->locators = cfargs->locators;
1121 args->devhandle = cfargs->devhandle; 1121 args->devhandle = cfargs->devhandle;
1122 1122
1123 return args; 1123 return args;
1124} 1124}
1125 1125
1126/* 1126/*
1127 * Iterate over all potential children of some device, calling the given 1127 * Iterate over all potential children of some device, calling the given
1128 * function (default being the child's match function) for each one. 1128 * function (default being the child's match function) for each one.
1129 * Nonzero returns are matches; the highest value returned is considered 1129 * Nonzero returns are matches; the highest value returned is considered
1130 * the best match. Return the `found child' if we got a match, or NULL 1130 * the best match. Return the `found child' if we got a match, or NULL
1131 * otherwise. The `aux' pointer is simply passed on through. 1131 * otherwise. The `aux' pointer is simply passed on through.
1132 * 1132 *
1133 * Note that this function is designed so that it can be used to apply 1133 * Note that this function is designed so that it can be used to apply
1134 * an arbitrary function to all potential children (its return value 1134 * an arbitrary function to all potential children (its return value
1135 * can be ignored). 1135 * can be ignored).
1136 */ 1136 */
1137static cfdata_t 1137static cfdata_t
1138config_search_internal(device_t parent, void *aux, 1138config_search_internal(device_t parent, void *aux,
1139 const struct cfargs_internal * const args) 1139 const struct cfargs_internal * const args)
1140{ 1140{
1141 struct cftable *ct; 1141 struct cftable *ct;
1142 cfdata_t cf; 1142 cfdata_t cf;
1143 struct matchinfo m; 1143 struct matchinfo m;
1144 1144
1145 KASSERT(config_initialized); 1145 KASSERT(config_initialized);
1146 KASSERTMSG((!args->iattr || 1146 KASSERTMSG((!args->iattr ||
1147 cfdriver_get_iattr(parent->dv_cfdriver, args->iattr)), 1147 cfdriver_get_iattr(parent->dv_cfdriver, args->iattr)),
1148 "%s searched for child at interface attribute %s," 1148 "%s searched for child at interface attribute %s,"
1149 " but device %s(4) has no such interface attribute in config(5)", 1149 " but device %s(4) has no such interface attribute in config(5)",
1150 device_xname(parent), args->iattr, 1150 device_xname(parent), args->iattr,
1151 parent->dv_cfdriver->cd_name); 1151 parent->dv_cfdriver->cd_name);
1152 KASSERTMSG((args->iattr || 1152 KASSERTMSG((args->iattr ||
1153 cfdriver_iattr_count(parent->dv_cfdriver) < 2), 1153 cfdriver_iattr_count(parent->dv_cfdriver) < 2),
1154 "%s searched for child without interface attribute," 1154 "%s searched for child without interface attribute,"
1155 " needed to disambiguate among the %d declared for in %s(4)" 1155 " needed to disambiguate among the %d declared for in %s(4)"
1156 " in config(5)", 1156 " in config(5)",
1157 device_xname(parent), 1157 device_xname(parent),
1158 cfdriver_iattr_count(parent->dv_cfdriver), 1158 cfdriver_iattr_count(parent->dv_cfdriver),
1159 parent->dv_cfdriver->cd_name); 1159 parent->dv_cfdriver->cd_name);
1160 1160
1161 m.fn = args->submatch; /* N.B. union */ 1161 m.fn = args->submatch; /* N.B. union */
1162 m.parent = parent; 1162 m.parent = parent;
1163 m.locs = args->locators; 1163 m.locs = args->locators;
1164 m.aux = aux; 1164 m.aux = aux;
1165 m.match = NULL; 1165 m.match = NULL;
1166 m.pri = 0; 1166 m.pri = 0;
1167 1167
1168 TAILQ_FOREACH(ct, &allcftables, ct_list) { 1168 TAILQ_FOREACH(ct, &allcftables, ct_list) {
1169 for (cf = ct->ct_cfdata; cf->cf_name; cf++) { 1169 for (cf = ct->ct_cfdata; cf->cf_name; cf++) {
1170 1170
1171 /* We don't match root nodes here. */ 1171 /* We don't match root nodes here. */
1172 if (!cf->cf_pspec) 1172 if (!cf->cf_pspec)
1173 continue; 1173 continue;
1174 1174
1175 /* 1175 /*
1176 * Skip cf if no longer eligible, otherwise scan 1176 * Skip cf if no longer eligible, otherwise scan
1177 * through parents for one matching `parent', and 1177 * through parents for one matching `parent', and
1178 * try match function. 1178 * try match function.
1179 */ 1179 */
1180 if (cf->cf_fstate == FSTATE_FOUND) 1180 if (cf->cf_fstate == FSTATE_FOUND)
1181 continue; 1181 continue;
1182 if (cf->cf_fstate == FSTATE_DNOTFOUND || 1182 if (cf->cf_fstate == FSTATE_DNOTFOUND ||
1183 cf->cf_fstate == FSTATE_DSTAR) 1183 cf->cf_fstate == FSTATE_DSTAR)
1184 continue; 1184 continue;
1185 1185
1186 /* 1186 /*
1187 * If an interface attribute was specified, 1187 * If an interface attribute was specified,
1188 * consider only children which attach to 1188 * consider only children which attach to
1189 * that attribute. 1189 * that attribute.
1190 */ 1190 */
1191 if (args->iattr != NULL && 1191 if (args->iattr != NULL &&
1192 !STREQ(args->iattr, cfdata_ifattr(cf))) 1192 !STREQ(args->iattr, cfdata_ifattr(cf)))
1193 continue; 1193 continue;
1194 1194
1195 if (cfparent_match(parent, cf->cf_pspec)) 1195 if (cfparent_match(parent, cf->cf_pspec))
1196 mapply(&m, cf); 1196 mapply(&m, cf);
1197 } 1197 }
1198 } 1198 }
1199 rnd_add_uint32(&rnd_autoconf_source, 0); 1199 rnd_add_uint32(&rnd_autoconf_source, 0);
1200 return m.match; 1200 return m.match;
1201} 1201}
1202 1202
1203cfdata_t 1203cfdata_t
1204config_search(device_t parent, void *aux, const struct cfargs *cfargs) 1204config_search(device_t parent, void *aux, const struct cfargs *cfargs)
1205{ 1205{
1206 cfdata_t cf; 1206 cfdata_t cf;
1207 struct cfargs_internal store; 1207 struct cfargs_internal store;
1208 1208
1209 cf = config_search_internal(parent, aux, 1209 cf = config_search_internal(parent, aux,
1210 cfargs_canonicalize(cfargs, &store)); 1210 cfargs_canonicalize(cfargs, &store));
1211 1211
1212 return cf; 1212 return cf;
1213} 1213}
1214 1214
1215/* 1215/*
1216 * Find the given root device. 1216 * Find the given root device.
1217 * This is much like config_search, but there is no parent. 1217 * This is much like config_search, but there is no parent.
1218 * Don't bother with multiple cfdata tables; the root node 1218 * Don't bother with multiple cfdata tables; the root node
1219 * must always be in the initial table. 1219 * must always be in the initial table.
1220 */ 1220 */
1221cfdata_t 1221cfdata_t
1222config_rootsearch(cfsubmatch_t fn, const char *rootname, void *aux) 1222config_rootsearch(cfsubmatch_t fn, const char *rootname, void *aux)
1223{ 1223{
1224 cfdata_t cf; 1224 cfdata_t cf;
1225 const short *p; 1225 const short *p;
1226 struct matchinfo m; 1226 struct matchinfo m;
1227 1227
1228 m.fn = fn; 1228 m.fn = fn;
1229 m.parent = ROOT; 1229 m.parent = ROOT;
1230 m.aux = aux; 1230 m.aux = aux;
1231 m.match = NULL; 1231 m.match = NULL;
1232 m.pri = 0; 1232 m.pri = 0;
1233 m.locs = 0; 1233 m.locs = 0;
1234 /* 1234 /*
1235 * Look at root entries for matching name. We do not bother 1235 * Look at root entries for matching name. We do not bother
1236 * with found-state here since only one root should ever be 1236 * with found-state here since only one root should ever be
1237 * searched (and it must be done first). 1237 * searched (and it must be done first).
1238 */ 1238 */
1239 for (p = cfroots; *p >= 0; p++) { 1239 for (p = cfroots; *p >= 0; p++) {
1240 cf = &cfdata[*p]; 1240 cf = &cfdata[*p];
1241 if (strcmp(cf->cf_name, rootname) == 0) 1241 if (strcmp(cf->cf_name, rootname) == 0)
1242 mapply(&m, cf); 1242 mapply(&m, cf);
1243 } 1243 }
1244 return m.match; 1244 return m.match;
1245} 1245}
1246 1246
1247static const char * const msgs[] = { 1247static const char * const msgs[] = {
1248[QUIET] = "", 1248[QUIET] = "",
1249[UNCONF] = " not configured\n", 1249[UNCONF] = " not configured\n",
1250[UNSUPP] = " unsupported\n", 1250[UNSUPP] = " unsupported\n",
1251}; 1251};
1252 1252
1253/* 1253/*
1254 * The given `aux' argument describes a device that has been found 1254 * The given `aux' argument describes a device that has been found
1255 * on the given parent, but not necessarily configured. Locate the 1255 * on the given parent, but not necessarily configured. Locate the
1256 * configuration data for that device (using the submatch function 1256 * configuration data for that device (using the submatch function
1257 * provided, or using candidates' cd_match configuration driver 1257 * provided, or using candidates' cd_match configuration driver
1258 * functions) and attach it, and return its device_t. If the device was 1258 * functions) and attach it, and return its device_t. If the device was
1259 * not configured, call the given `print' function and return NULL. 1259 * not configured, call the given `print' function and return NULL.
1260 */ 1260 */
1261device_t 1261device_t
1262config_found(device_t parent, void *aux, cfprint_t print, 1262config_found(device_t parent, void *aux, cfprint_t print,
1263 const struct cfargs * const cfargs) 1263 const struct cfargs * const cfargs)
1264{ 1264{
1265 cfdata_t cf; 1265 cfdata_t cf;
1266 struct cfargs_internal store; 1266 struct cfargs_internal store;
1267 const struct cfargs_internal * const args = 1267 const struct cfargs_internal * const args =
1268 cfargs_canonicalize(cfargs, &store); 1268 cfargs_canonicalize(cfargs, &store);
1269 1269
1270 cf = config_search_internal(parent, aux, args); 1270 cf = config_search_internal(parent, aux, args);
1271 if (cf != NULL) { 1271 if (cf != NULL) {
1272 return config_attach_internal(parent, cf, aux, print, args); 1272 return config_attach_internal(parent, cf, aux, print, args);
1273 } 1273 }
1274 1274
1275 if (print) { 1275 if (print) {
1276 if (config_do_twiddle && cold) 1276 if (config_do_twiddle && cold)
1277 twiddle(); 1277 twiddle();
1278 1278
1279 const int pret = (*print)(aux, device_xname(parent)); 1279 const int pret = (*print)(aux, device_xname(parent));
1280 KASSERT(pret >= 0); 1280 KASSERT(pret >= 0);
1281 KASSERT(pret < __arraycount(msgs)); 1281 KASSERT(pret < __arraycount(msgs));
1282 KASSERT(msgs[pret] != NULL); 1282 KASSERT(msgs[pret] != NULL);
1283 aprint_normal("%s", msgs[pret]); 1283 aprint_normal("%s", msgs[pret]);
1284 } 1284 }
1285 1285
1286 return NULL; 1286 return NULL;
1287} 1287}
1288 1288
1289/* 1289/*
1290 * As above, but for root devices. 1290 * As above, but for root devices.
1291 */ 1291 */
1292device_t 1292device_t
1293config_rootfound(const char *rootname, void *aux) 1293config_rootfound(const char *rootname, void *aux)
1294{ 1294{
1295 cfdata_t cf; 1295 cfdata_t cf;
1296 device_t dev = NULL; 1296 device_t dev = NULL;
1297 1297
1298 KERNEL_LOCK(1, NULL); 1298 KERNEL_LOCK(1, NULL);
1299 if ((cf = config_rootsearch(NULL, rootname, aux)) != NULL) 1299 if ((cf = config_rootsearch(NULL, rootname, aux)) != NULL)
1300 dev = config_attach(ROOT, cf, aux, NULL, CFARGS_NONE); 1300 dev = config_attach(ROOT, cf, aux, NULL, CFARGS_NONE);
1301 else 1301 else
1302 aprint_error("root device %s not configured\n", rootname); 1302 aprint_error("root device %s not configured\n", rootname);
1303 KERNEL_UNLOCK_ONE(NULL); 1303 KERNEL_UNLOCK_ONE(NULL);
1304 return dev; 1304 return dev;
1305} 1305}
1306 1306
1307/* just like sprintf(buf, "%d") except that it works from the end */ 1307/* just like sprintf(buf, "%d") except that it works from the end */
1308static char * 1308static char *
1309number(char *ep, int n) 1309number(char *ep, int n)
1310{ 1310{
1311 1311
1312 *--ep = 0; 1312 *--ep = 0;
1313 while (n >= 10) { 1313 while (n >= 10) {
1314 *--ep = (n % 10) + '0'; 1314 *--ep = (n % 10) + '0';
1315 n /= 10; 1315 n /= 10;
1316 } 1316 }
1317 *--ep = n + '0'; 1317 *--ep = n + '0';
1318 return ep; 1318 return ep;
1319} 1319}
1320 1320
1321/* 1321/*
1322 * Expand the size of the cd_devs array if necessary. 1322 * Expand the size of the cd_devs array if necessary.
1323 * 1323 *
1324 * The caller must hold alldevs_lock. config_makeroom() may release and 1324 * The caller must hold alldevs_lock. config_makeroom() may release and
1325 * re-acquire alldevs_lock, so callers should re-check conditions such 1325 * re-acquire alldevs_lock, so callers should re-check conditions such
1326 * as alldevs_nwrite == 0 and alldevs_nread == 0 when config_makeroom() 1326 * as alldevs_nwrite == 0 and alldevs_nread == 0 when config_makeroom()
1327 * returns. 1327 * returns.
1328 */ 1328 */
1329static void 1329static void
1330config_makeroom(int n, struct cfdriver *cd) 1330config_makeroom(int n, struct cfdriver *cd)
1331{ 1331{
1332 int ondevs, nndevs; 1332 int ondevs, nndevs;
1333 device_t *osp, *nsp; 1333 device_t *osp, *nsp;
1334 1334
1335 KASSERT(mutex_owned(&alldevs_lock)); 1335 KASSERT(mutex_owned(&alldevs_lock));
1336 alldevs_nwrite++; 1336 alldevs_nwrite++;
1337 1337
1338 for (nndevs = MAX(4, cd->cd_ndevs); nndevs <= n; nndevs += nndevs) 1338 for (nndevs = MAX(4, cd->cd_ndevs); nndevs <= n; nndevs += nndevs)
1339 ; 1339 ;
1340 1340
1341 while (n >= cd->cd_ndevs) { 1341 while (n >= cd->cd_ndevs) {
1342 /* 1342 /*
1343 * Need to expand the array. 1343 * Need to expand the array.
1344 */ 1344 */
1345 ondevs = cd->cd_ndevs; 1345 ondevs = cd->cd_ndevs;
1346 osp = cd->cd_devs; 1346 osp = cd->cd_devs;
1347 1347
1348 /* 1348 /*
1349 * Release alldevs_lock around allocation, which may 1349 * Release alldevs_lock around allocation, which may
1350 * sleep. 1350 * sleep.
1351 */ 1351 */
1352 mutex_exit(&alldevs_lock); 1352 mutex_exit(&alldevs_lock);
1353 nsp = kmem_alloc(sizeof(device_t) * nndevs, KM_SLEEP); 1353 nsp = kmem_alloc(sizeof(device_t) * nndevs, KM_SLEEP);
1354 mutex_enter(&alldevs_lock); 1354 mutex_enter(&alldevs_lock);
1355 1355
1356 /* 1356 /*
1357 * If another thread moved the array while we did 1357 * If another thread moved the array while we did
1358 * not hold alldevs_lock, try again. 1358 * not hold alldevs_lock, try again.
1359 */ 1359 */
1360 if (cd->cd_devs != osp) { 1360 if (cd->cd_devs != osp || cd->cd_ndevs != ondevs) {
1361 mutex_exit(&alldevs_lock); 1361 mutex_exit(&alldevs_lock);
1362 kmem_free(nsp, sizeof(device_t) * nndevs); 1362 kmem_free(nsp, sizeof(device_t) * nndevs);
1363 mutex_enter(&alldevs_lock); 1363 mutex_enter(&alldevs_lock);
1364 continue; 1364 continue;
1365 } 1365 }
1366 1366
1367 memset(nsp + ondevs, 0, sizeof(device_t) * (nndevs - ondevs)); 1367 memset(nsp + ondevs, 0, sizeof(device_t) * (nndevs - ondevs));
1368 if (ondevs != 0) 1368 if (ondevs != 0)
1369 memcpy(nsp, cd->cd_devs, sizeof(device_t) * ondevs); 1369 memcpy(nsp, cd->cd_devs, sizeof(device_t) * ondevs);
1370 1370
1371 cd->cd_ndevs = nndevs; 1371 cd->cd_ndevs = nndevs;
1372 cd->cd_devs = nsp; 1372 cd->cd_devs = nsp;
1373 if (ondevs != 0) { 1373 if (ondevs != 0) {
1374 mutex_exit(&alldevs_lock); 1374 mutex_exit(&alldevs_lock);
1375 kmem_free(osp, sizeof(device_t) * ondevs); 1375 kmem_free(osp, sizeof(device_t) * ondevs);
1376 mutex_enter(&alldevs_lock); 1376 mutex_enter(&alldevs_lock);
1377 } 1377 }
1378 } 1378 }
1379 KASSERT(mutex_owned(&alldevs_lock)); 1379 KASSERT(mutex_owned(&alldevs_lock));
1380 alldevs_nwrite--; 1380 alldevs_nwrite--;
1381} 1381}
1382 1382
1383/* 1383/*
1384 * Put dev into the devices list. 1384 * Put dev into the devices list.
1385 */ 1385 */
1386static void 1386static void
1387config_devlink(device_t dev) 1387config_devlink(device_t dev)
1388{ 1388{
1389 1389
1390 mutex_enter(&alldevs_lock); 1390 mutex_enter(&alldevs_lock);
1391 1391
1392 KASSERT(device_cfdriver(dev)->cd_devs[dev->dv_unit] == dev); 1392 KASSERT(device_cfdriver(dev)->cd_devs[dev->dv_unit] == dev);
1393 1393
1394 dev->dv_add_gen = alldevs_gen; 1394 dev->dv_add_gen = alldevs_gen;
1395 /* It is safe to add a device to the tail of the list while 1395 /* It is safe to add a device to the tail of the list while
1396 * readers and writers are in the list. 1396 * readers and writers are in the list.
1397 */ 1397 */
1398 TAILQ_INSERT_TAIL(&alldevs, dev, dv_list); 1398 TAILQ_INSERT_TAIL(&alldevs, dev, dv_list);
1399 mutex_exit(&alldevs_lock); 1399 mutex_exit(&alldevs_lock);
1400} 1400}
1401 1401
1402static void 1402static void
1403config_devfree(device_t dev) 1403config_devfree(device_t dev)
1404{ 1404{
1405 1405
1406 KASSERT(dev->dv_flags & DVF_PRIV_ALLOC); 1406 KASSERT(dev->dv_flags & DVF_PRIV_ALLOC);
1407 KASSERTMSG(dev->dv_pending == 0, "%d", dev->dv_pending); 1407 KASSERTMSG(dev->dv_pending == 0, "%d", dev->dv_pending);
1408 1408
1409 if (dev->dv_cfattach->ca_devsize > 0) 1409 if (dev->dv_cfattach->ca_devsize > 0)
1410 kmem_free(dev->dv_private, dev->dv_cfattach->ca_devsize); 1410 kmem_free(dev->dv_private, dev->dv_cfattach->ca_devsize);
1411 kmem_free(dev, sizeof(*dev)); 1411 kmem_free(dev, sizeof(*dev));
1412} 1412}
1413 1413
1414/* 1414/*
1415 * Caller must hold alldevs_lock. 1415 * Caller must hold alldevs_lock.
1416 */ 1416 */
1417static void 1417static void
1418config_devunlink(device_t dev, struct devicelist *garbage) 1418config_devunlink(device_t dev, struct devicelist *garbage)
1419{ 1419{
1420 struct device_garbage *dg = &dev->dv_garbage; 1420 struct device_garbage *dg = &dev->dv_garbage;
1421 cfdriver_t cd = device_cfdriver(dev); 1421 cfdriver_t cd = device_cfdriver(dev);
1422 int i; 1422 int i;
1423 1423
1424 KASSERT(mutex_owned(&alldevs_lock)); 1424 KASSERT(mutex_owned(&alldevs_lock));
1425 KASSERTMSG(dev->dv_pending == 0, "%d", dev->dv_pending); 1425 KASSERTMSG(dev->dv_pending == 0, "%d", dev->dv_pending);
1426 1426
1427 /* Unlink from device list. Link to garbage list. */ 1427 /* Unlink from device list. Link to garbage list. */
1428 TAILQ_REMOVE(&alldevs, dev, dv_list); 1428 TAILQ_REMOVE(&alldevs, dev, dv_list);
1429 TAILQ_INSERT_TAIL(garbage, dev, dv_list); 1429 TAILQ_INSERT_TAIL(garbage, dev, dv_list);
1430 1430
1431 /* Remove from cfdriver's array. */ 1431 /* Remove from cfdriver's array. */
1432 cd->cd_devs[dev->dv_unit] = NULL; 1432 cd->cd_devs[dev->dv_unit] = NULL;
1433 1433
1434 /* 1434 /*
1435 * If the device now has no units in use, unlink its softc array. 1435 * If the device now has no units in use, unlink its softc array.
1436 */ 1436 */
1437 for (i = 0; i < cd->cd_ndevs; i++) { 1437 for (i = 0; i < cd->cd_ndevs; i++) {
1438 if (cd->cd_devs[i] != NULL) 1438 if (cd->cd_devs[i] != NULL)
1439 break; 1439 break;
1440 } 1440 }
1441 /* Nothing found. Unlink, now. Deallocate, later. */ 1441 /* Nothing found. Unlink, now. Deallocate, later. */
1442 if (i == cd->cd_ndevs) { 1442 if (i == cd->cd_ndevs) {
1443 dg->dg_ndevs = cd->cd_ndevs; 1443 dg->dg_ndevs = cd->cd_ndevs;
1444 dg->dg_devs = cd->cd_devs; 1444 dg->dg_devs = cd->cd_devs;
1445 cd->cd_devs = NULL; 1445 cd->cd_devs = NULL;
1446 cd->cd_ndevs = 0; 1446 cd->cd_ndevs = 0;
1447 } 1447 }
1448} 1448}
1449 1449
1450static void 1450static void
1451config_devdelete(device_t dev) 1451config_devdelete(device_t dev)
1452{ 1452{
1453 struct device_garbage *dg = &dev->dv_garbage; 1453 struct device_garbage *dg = &dev->dv_garbage;
1454 device_lock_t dvl = device_getlock(dev); 1454 device_lock_t dvl = device_getlock(dev);
1455 1455
1456 KASSERTMSG(dev->dv_pending == 0, "%d", dev->dv_pending); 1456 KASSERTMSG(dev->dv_pending == 0, "%d", dev->dv_pending);
1457 1457
1458 if (dg->dg_devs != NULL) 1458 if (dg->dg_devs != NULL)
1459 kmem_free(dg->dg_devs, sizeof(device_t) * dg->dg_ndevs); 1459 kmem_free(dg->dg_devs, sizeof(device_t) * dg->dg_ndevs);
1460 1460
1461 localcount_fini(dev->dv_localcount); 1461 localcount_fini(dev->dv_localcount);
1462 kmem_free(dev->dv_localcount, sizeof(*dev->dv_localcount)); 1462 kmem_free(dev->dv_localcount, sizeof(*dev->dv_localcount));
1463 1463
1464 cv_destroy(&dvl->dvl_cv); 1464 cv_destroy(&dvl->dvl_cv);
1465 mutex_destroy(&dvl->dvl_mtx); 1465 mutex_destroy(&dvl->dvl_mtx);
1466 1466
1467 KASSERT(dev->dv_properties != NULL); 1467 KASSERT(dev->dv_properties != NULL);
1468 prop_object_release(dev->dv_properties); 1468 prop_object_release(dev->dv_properties);
1469 1469
1470 if (dev->dv_activity_handlers) 1470 if (dev->dv_activity_handlers)
1471 panic("%s with registered handlers", __func__); 1471 panic("%s with registered handlers", __func__);
1472 1472
1473 if (dev->dv_locators) { 1473 if (dev->dv_locators) {
1474 size_t amount = *--dev->dv_locators; 1474 size_t amount = *--dev->dv_locators;
1475 kmem_free(dev->dv_locators, amount); 1475 kmem_free(dev->dv_locators, amount);
1476 } 1476 }
1477 1477
1478 config_devfree(dev); 1478 config_devfree(dev);
1479} 1479}
1480 1480
1481static int 1481static int
1482config_unit_nextfree(cfdriver_t cd, cfdata_t cf) 1482config_unit_nextfree(cfdriver_t cd, cfdata_t cf)
1483{ 1483{
1484 int unit = cf->cf_unit; 1484 int unit = cf->cf_unit;
1485 1485
1486 if (unit < 0) 1486 if (unit < 0)
1487 return -1; 1487 return -1;
1488 if (cf->cf_fstate == FSTATE_STAR) { 1488 if (cf->cf_fstate == FSTATE_STAR) {
1489 for (; unit < cd->cd_ndevs; unit++) 1489 for (; unit < cd->cd_ndevs; unit++)
1490 if (cd->cd_devs[unit] == NULL) 1490 if (cd->cd_devs[unit] == NULL)
1491 break; 1491 break;
1492 /* 1492 /*
1493 * unit is now the unit of the first NULL device pointer, 1493 * unit is now the unit of the first NULL device pointer,
1494 * or max(cd->cd_ndevs,cf->cf_unit). 1494 * or max(cd->cd_ndevs,cf->cf_unit).
1495 */ 1495 */
1496 } else { 1496 } else {
1497 if (unit < cd->cd_ndevs && cd->cd_devs[unit] != NULL) 1497 if (unit < cd->cd_ndevs && cd->cd_devs[unit] != NULL)
1498 unit = -1; 1498 unit = -1;
1499 } 1499 }
1500 return unit; 1500 return unit;
1501} 1501}
1502 1502
1503static int 1503static int
1504config_unit_alloc(device_t dev, cfdriver_t cd, cfdata_t cf) 1504config_unit_alloc(device_t dev, cfdriver_t cd, cfdata_t cf)
1505{ 1505{
1506 struct alldevs_foray af; 1506 struct alldevs_foray af;
1507 int unit; 1507 int unit;
1508 1508
1509 config_alldevs_enter(&af); 1509 config_alldevs_enter(&af);
1510 for (;;) { 1510 for (;;) {
1511 unit = config_unit_nextfree(cd, cf); 1511 unit = config_unit_nextfree(cd, cf);
1512 if (unit == -1) 1512 if (unit == -1)
1513 break; 1513 break;
1514 if (unit < cd->cd_ndevs) { 1514 if (unit < cd->cd_ndevs) {
1515 cd->cd_devs[unit] = dev; 1515 cd->cd_devs[unit] = dev;
1516 dev->dv_unit = unit; 1516 dev->dv_unit = unit;
1517 break; 1517 break;
1518 } 1518 }
1519 config_makeroom(unit, cd); 1519 config_makeroom(unit, cd);
1520 } 1520 }
1521 config_alldevs_exit(&af); 1521 config_alldevs_exit(&af);
1522 1522
1523 return unit; 1523 return unit;
1524} 1524}
1525 1525
1526static device_t 1526static device_t
1527config_devalloc(const device_t parent, const cfdata_t cf, 1527config_devalloc(const device_t parent, const cfdata_t cf,
1528 const struct cfargs_internal * const args) 1528 const struct cfargs_internal * const args)
1529{ 1529{
1530 cfdriver_t cd; 1530 cfdriver_t cd;
1531 cfattach_t ca; 1531 cfattach_t ca;
1532 size_t lname, lunit; 1532 size_t lname, lunit;
1533 const char *xunit; 1533 const char *xunit;
1534 int myunit; 1534 int myunit;
1535 char num[10]; 1535 char num[10];
1536 device_t dev; 1536 device_t dev;
1537 void *dev_private; 1537 void *dev_private;
1538 const struct cfiattrdata *ia; 1538 const struct cfiattrdata *ia;
1539 device_lock_t dvl; 1539 device_lock_t dvl;
1540 1540
1541 cd = config_cfdriver_lookup(cf->cf_name); 1541 cd = config_cfdriver_lookup(cf->cf_name);
1542 if (cd == NULL) 1542 if (cd == NULL)
1543 return NULL; 1543 return NULL;
1544 1544
1545 ca = config_cfattach_lookup_cd(cd, cf->cf_atname); 1545 ca = config_cfattach_lookup_cd(cd, cf->cf_atname);
1546 if (ca == NULL) 1546 if (ca == NULL)
1547 return NULL; 1547 return NULL;
1548 1548
1549 /* get memory for all device vars */ 1549 /* get memory for all device vars */
1550 KASSERT(ca->ca_flags & DVF_PRIV_ALLOC); 1550 KASSERT(ca->ca_flags & DVF_PRIV_ALLOC);
1551 if (ca->ca_devsize > 0) { 1551 if (ca->ca_devsize > 0) {
1552 dev_private = kmem_zalloc(ca->ca_devsize, KM_SLEEP); 1552 dev_private = kmem_zalloc(ca->ca_devsize, KM_SLEEP);
1553 } else { 1553 } else {
1554 dev_private = NULL; 1554 dev_private = NULL;
1555 } 1555 }
1556 dev = kmem_zalloc(sizeof(*dev), KM_SLEEP); 1556 dev = kmem_zalloc(sizeof(*dev), KM_SLEEP);
1557 1557
1558 dev->dv_handle = args->devhandle; 1558 dev->dv_handle = args->devhandle;
1559 1559
1560 dev->dv_class = cd->cd_class; 1560 dev->dv_class = cd->cd_class;
1561 dev->dv_cfdata = cf; 1561 dev->dv_cfdata = cf;
1562 dev->dv_cfdriver = cd; 1562 dev->dv_cfdriver = cd;
1563 dev->dv_cfattach = ca; 1563 dev->dv_cfattach = ca;
1564 dev->dv_activity_count = 0; 1564 dev->dv_activity_count = 0;
1565 dev->dv_activity_handlers = NULL; 1565 dev->dv_activity_handlers = NULL;
1566 dev->dv_private = dev_private; 1566 dev->dv_private = dev_private;
1567 dev->dv_flags = ca->ca_flags; /* inherit flags from class */ 1567 dev->dv_flags = ca->ca_flags; /* inherit flags from class */
1568 dev->dv_attaching = curlwp; 1568 dev->dv_attaching = curlwp;
1569 1569
1570 myunit = config_unit_alloc(dev, cd, cf); 1570 myunit = config_unit_alloc(dev, cd, cf);
1571 if (myunit == -1) { 1571 if (myunit == -1) {
1572 config_devfree(dev); 1572 config_devfree(dev);
1573 return NULL; 1573 return NULL;
1574 } 1574 }
1575 1575
1576 /* compute length of name and decimal expansion of unit number */ 1576 /* compute length of name and decimal expansion of unit number */
1577 lname = strlen(cd->cd_name); 1577 lname = strlen(cd->cd_name);
1578 xunit = number(&num[sizeof(num)], myunit); 1578 xunit = number(&num[sizeof(num)], myunit);
1579 lunit = &num[sizeof(num)] - xunit; 1579 lunit = &num[sizeof(num)] - xunit;
1580 if (lname + lunit > sizeof(dev->dv_xname)) 1580 if (lname + lunit > sizeof(dev->dv_xname))
1581 panic("config_devalloc: device name too long"); 1581 panic("config_devalloc: device name too long");
1582 1582
1583 dvl = device_getlock(dev); 1583 dvl = device_getlock(dev);
1584 1584
1585 mutex_init(&dvl->dvl_mtx, MUTEX_DEFAULT, IPL_NONE); 1585 mutex_init(&dvl->dvl_mtx, MUTEX_DEFAULT, IPL_NONE);
1586 cv_init(&dvl->dvl_cv, "pmfsusp"); 1586 cv_init(&dvl->dvl_cv, "pmfsusp");
1587 1587
1588 memcpy(dev->dv_xname, cd->cd_name, lname); 1588 memcpy(dev->dv_xname, cd->cd_name, lname);
1589 memcpy(dev->dv_xname + lname, xunit, lunit); 1589 memcpy(dev->dv_xname + lname, xunit, lunit);
1590 dev->dv_parent = parent; 1590 dev->dv_parent = parent;
1591 if (parent != NULL) 1591 if (parent != NULL)
1592 dev->dv_depth = parent->dv_depth + 1; 1592 dev->dv_depth = parent->dv_depth + 1;
1593 else 1593 else
1594 dev->dv_depth = 0; 1594 dev->dv_depth = 0;
1595 dev->dv_flags |= DVF_ACTIVE; /* always initially active */ 1595 dev->dv_flags |= DVF_ACTIVE; /* always initially active */
1596 if (args->locators) { 1596 if (args->locators) {
1597 KASSERT(parent); /* no locators at root */ 1597 KASSERT(parent); /* no locators at root */
1598 ia = cfiattr_lookup(cfdata_ifattr(cf), parent->dv_cfdriver); 1598 ia = cfiattr_lookup(cfdata_ifattr(cf), parent->dv_cfdriver);
1599 dev->dv_locators = 1599 dev->dv_locators =
1600 kmem_alloc(sizeof(int) * (ia->ci_loclen + 1), KM_SLEEP); 1600 kmem_alloc(sizeof(int) * (ia->ci_loclen + 1), KM_SLEEP);
1601 *dev->dv_locators++ = sizeof(int) * (ia->ci_loclen + 1); 1601 *dev->dv_locators++ = sizeof(int) * (ia->ci_loclen + 1);
1602 memcpy(dev->dv_locators, args->locators, 1602 memcpy(dev->dv_locators, args->locators,
1603 sizeof(int) * ia->ci_loclen); 1603 sizeof(int) * ia->ci_loclen);
1604 } 1604 }
1605 dev->dv_properties = prop_dictionary_create(); 1605 dev->dv_properties = prop_dictionary_create();
1606 KASSERT(dev->dv_properties != NULL); 1606 KASSERT(dev->dv_properties != NULL);
1607 1607
1608 prop_dictionary_set_string_nocopy(dev->dv_properties, 1608 prop_dictionary_set_string_nocopy(dev->dv_properties,
1609 "device-driver", dev->dv_cfdriver->cd_name); 1609 "device-driver", dev->dv_cfdriver->cd_name);
1610 prop_dictionary_set_uint16(dev->dv_properties, 1610 prop_dictionary_set_uint16(dev->dv_properties,
1611 "device-unit", dev->dv_unit); 1611 "device-unit", dev->dv_unit);
1612 if (parent != NULL) { 1612 if (parent != NULL) {
1613 prop_dictionary_set_string(dev->dv_properties, 1613 prop_dictionary_set_string(dev->dv_properties,
1614 "device-parent", device_xname(parent)); 1614 "device-parent", device_xname(parent));
1615 } 1615 }
1616 1616
1617 dev->dv_localcount = kmem_zalloc(sizeof(*dev->dv_localcount), 1617 dev->dv_localcount = kmem_zalloc(sizeof(*dev->dv_localcount),
1618 KM_SLEEP); 1618 KM_SLEEP);
1619 localcount_init(dev->dv_localcount); 1619 localcount_init(dev->dv_localcount);
1620 1620
1621 if (dev->dv_cfdriver->cd_attrs != NULL) 1621 if (dev->dv_cfdriver->cd_attrs != NULL)
1622 config_add_attrib_dict(dev); 1622 config_add_attrib_dict(dev);
1623 1623
1624 return dev; 1624 return dev;
1625} 1625}
1626 1626
1627/* 1627/*
1628 * Create an array of device attach attributes and add it 1628 * Create an array of device attach attributes and add it
1629 * to the device's dv_properties dictionary. 1629 * to the device's dv_properties dictionary.
1630 * 1630 *
1631 * <key>interface-attributes</key> 1631 * <key>interface-attributes</key>
1632 * <array> 1632 * <array>
1633 * <dict> 1633 * <dict>
1634 * <key>attribute-name</key> 1634 * <key>attribute-name</key>
1635 * <string>foo</string> 1635 * <string>foo</string>
1636 * <key>locators</key> 1636 * <key>locators</key>
1637 * <array> 1637 * <array>
1638 * <dict> 1638 * <dict>
1639 * <key>loc-name</key> 1639 * <key>loc-name</key>
1640 * <string>foo-loc1</string> 1640 * <string>foo-loc1</string>
1641 * </dict> 1641 * </dict>
1642 * <dict> 1642 * <dict>
1643 * <key>loc-name</key> 1643 * <key>loc-name</key>
1644 * <string>foo-loc2</string> 1644 * <string>foo-loc2</string>
1645 * <key>default</key> 1645 * <key>default</key>
1646 * <string>foo-loc2-default</string> 1646 * <string>foo-loc2-default</string>
1647 * </dict> 1647 * </dict>
1648 * ... 1648 * ...
1649 * </array> 1649 * </array>
1650 * </dict> 1650 * </dict>
1651 * ... 1651 * ...
1652 * </array> 1652 * </array>
1653 */ 1653 */
1654 1654
1655static void 1655static void
1656config_add_attrib_dict(device_t dev) 1656config_add_attrib_dict(device_t dev)
1657{ 1657{
1658 int i, j; 1658 int i, j;
1659 const struct cfiattrdata *ci; 1659 const struct cfiattrdata *ci;
1660 prop_dictionary_t attr_dict, loc_dict; 1660 prop_dictionary_t attr_dict, loc_dict;
1661 prop_array_t attr_array, loc_array; 1661 prop_array_t attr_array, loc_array;
1662 1662
1663 if ((attr_array = prop_array_create()) == NULL) 1663 if ((attr_array = prop_array_create()) == NULL)
1664 return; 1664 return;
1665 1665
1666 for (i = 0; ; i++) { 1666 for (i = 0; ; i++) {
1667 if ((ci = dev->dv_cfdriver->cd_attrs[i]) == NULL) 1667 if ((ci = dev->dv_cfdriver->cd_attrs[i]) == NULL)
1668 break; 1668 break;
1669 if ((attr_dict = prop_dictionary_create()) == NULL) 1669 if ((attr_dict = prop_dictionary_create()) == NULL)
1670 break; 1670 break;
1671 prop_dictionary_set_string_nocopy(attr_dict, "attribute-name", 1671 prop_dictionary_set_string_nocopy(attr_dict, "attribute-name",
1672 ci->ci_name); 1672 ci->ci_name);
1673 1673
1674 /* Create an array of the locator names and defaults */ 1674 /* Create an array of the locator names and defaults */
1675 1675
1676 if (ci->ci_loclen != 0 && 1676 if (ci->ci_loclen != 0 &&
1677 (loc_array = prop_array_create()) != NULL) { 1677 (loc_array = prop_array_create()) != NULL) {
1678 for (j = 0; j < ci->ci_loclen; j++) { 1678 for (j = 0; j < ci->ci_loclen; j++) {
1679 loc_dict = prop_dictionary_create(); 1679 loc_dict = prop_dictionary_create();
1680 if (loc_dict == NULL) 1680 if (loc_dict == NULL)
1681 continue; 1681 continue;
1682 prop_dictionary_set_string_nocopy(loc_dict, 1682 prop_dictionary_set_string_nocopy(loc_dict,
1683 "loc-name", ci->ci_locdesc[j].cld_name); 1683 "loc-name", ci->ci_locdesc[j].cld_name);
1684 if (ci->ci_locdesc[j].cld_defaultstr != NULL) 1684 if (ci->ci_locdesc[j].cld_defaultstr != NULL)
1685 prop_dictionary_set_string_nocopy( 1685 prop_dictionary_set_string_nocopy(
1686 loc_dict, "default", 1686 loc_dict, "default",
1687 ci->ci_locdesc[j].cld_defaultstr); 1687 ci->ci_locdesc[j].cld_defaultstr);
1688 prop_array_set(loc_array, j, loc_dict); 1688 prop_array_set(loc_array, j, loc_dict);
1689 prop_object_release(loc_dict); 1689 prop_object_release(loc_dict);
1690 } 1690 }
1691 prop_dictionary_set_and_rel(attr_dict, "locators", 1691 prop_dictionary_set_and_rel(attr_dict, "locators",
1692 loc_array); 1692 loc_array);
1693 } 1693 }
1694 prop_array_add(attr_array, attr_dict); 1694 prop_array_add(attr_array, attr_dict);
1695 prop_object_release(attr_dict); 1695 prop_object_release(attr_dict);
1696 } 1696 }
1697 if (i == 0) 1697 if (i == 0)
1698 prop_object_release(attr_array); 1698 prop_object_release(attr_array);
1699 else 1699 else
1700 prop_dictionary_set_and_rel(dev->dv_properties, 1700 prop_dictionary_set_and_rel(dev->dv_properties,
1701 "interface-attributes", attr_array); 1701 "interface-attributes", attr_array);
1702 1702
1703 return; 1703 return;
1704} 1704}
1705 1705
1706/* 1706/*
1707 * Attach a found device. 1707 * Attach a found device.
1708 */ 1708 */
1709static device_t 1709static device_t
1710config_attach_internal(device_t parent, cfdata_t cf, void *aux, cfprint_t print, 1710config_attach_internal(device_t parent, cfdata_t cf, void *aux, cfprint_t print,
1711 const struct cfargs_internal * const args) 1711 const struct cfargs_internal * const args)
1712{ 1712{
1713 device_t dev; 1713 device_t dev;
1714 struct cftable *ct; 1714 struct cftable *ct;
1715 const char *drvname; 1715 const char *drvname;
1716 bool deferred; 1716 bool deferred;
1717 1717
1718 KASSERT(KERNEL_LOCKED_P()); 1718 KASSERT(KERNEL_LOCKED_P());
1719 1719
1720 dev = config_devalloc(parent, cf, args); 1720 dev = config_devalloc(parent, cf, args);
1721 if (!dev) 1721 if (!dev)
1722 panic("config_attach: allocation of device softc failed"); 1722 panic("config_attach: allocation of device softc failed");
1723 1723
1724 /* XXX redundant - see below? */ 1724 /* XXX redundant - see below? */
1725 if (cf->cf_fstate != FSTATE_STAR) { 1725 if (cf->cf_fstate != FSTATE_STAR) {
1726 KASSERT(cf->cf_fstate == FSTATE_NOTFOUND); 1726 KASSERT(cf->cf_fstate == FSTATE_NOTFOUND);
1727 cf->cf_fstate = FSTATE_FOUND; 1727 cf->cf_fstate = FSTATE_FOUND;
1728 } 1728 }
1729 1729
1730 config_devlink(dev); 1730 config_devlink(dev);
1731 1731
1732 if (config_do_twiddle && cold) 1732 if (config_do_twiddle && cold)
1733 twiddle(); 1733 twiddle();
1734 else 1734 else
1735 aprint_naive("Found "); 1735 aprint_naive("Found ");
1736 /* 1736 /*
1737 * We want the next two printfs for normal, verbose, and quiet, 1737 * We want the next two printfs for normal, verbose, and quiet,
1738 * but not silent (in which case, we're twiddling, instead). 1738 * but not silent (in which case, we're twiddling, instead).
1739 */ 1739 */
1740 if (parent == ROOT) { 1740 if (parent == ROOT) {
1741 aprint_naive("%s (root)", device_xname(dev)); 1741 aprint_naive("%s (root)", device_xname(dev));
1742 aprint_normal("%s (root)", device_xname(dev)); 1742 aprint_normal("%s (root)", device_xname(dev));
1743 } else { 1743 } else {
1744 aprint_naive("%s at %s", device_xname(dev), 1744 aprint_naive("%s at %s", device_xname(dev),
1745 device_xname(parent)); 1745 device_xname(parent));
1746 aprint_normal("%s at %s", device_xname(dev), 1746 aprint_normal("%s at %s", device_xname(dev),
1747 device_xname(parent)); 1747 device_xname(parent));
1748 if (print) 1748 if (print)
1749 (void) (*print)(aux, NULL); 1749 (void) (*print)(aux, NULL);
1750 } 1750 }
1751 1751
1752 /* 1752 /*
1753 * Before attaching, clobber any unfound devices that are 1753 * Before attaching, clobber any unfound devices that are
1754 * otherwise identical. 1754 * otherwise identical.
1755 * XXX code above is redundant? 1755 * XXX code above is redundant?
1756 */ 1756 */
1757 drvname = dev->dv_cfdriver->cd_name; 1757 drvname = dev->dv_cfdriver->cd_name;
1758 TAILQ_FOREACH(ct, &allcftables, ct_list) { 1758 TAILQ_FOREACH(ct, &allcftables, ct_list) {
1759 for (cf = ct->ct_cfdata; cf->cf_name; cf++) { 1759 for (cf = ct->ct_cfdata; cf->cf_name; cf++) {
1760 if (STREQ(cf->cf_name, drvname) && 1760 if (STREQ(cf->cf_name, drvname) &&
1761 cf->cf_unit == dev->dv_unit) { 1761 cf->cf_unit == dev->dv_unit) {
1762 if (cf->cf_fstate == FSTATE_NOTFOUND) 1762 if (cf->cf_fstate == FSTATE_NOTFOUND)
1763 cf->cf_fstate = FSTATE_FOUND; 1763 cf->cf_fstate = FSTATE_FOUND;
1764 } 1764 }
1765 } 1765 }
1766 } 1766 }
1767 device_register(dev, aux); 1767 device_register(dev, aux);
1768 1768
1769 /* Let userland know */ 1769 /* Let userland know */
1770 devmon_report_device(dev, true); 1770 devmon_report_device(dev, true);
1771 1771
1772 /* 1772 /*
1773 * Prevent detach until the driver's attach function, and all 1773 * Prevent detach until the driver's attach function, and all
1774 * deferred actions, have finished. 1774 * deferred actions, have finished.
1775 */ 1775 */
1776 config_pending_incr(dev); 1776 config_pending_incr(dev);
1777 1777
1778 /* Call the driver's attach function. */ 1778 /* Call the driver's attach function. */
1779 (*dev->dv_cfattach->ca_attach)(parent, dev, aux); 1779 (*dev->dv_cfattach->ca_attach)(parent, dev, aux);
1780 1780
1781 /* 1781 /*
1782 * Allow other threads to acquire references to the device now 1782 * Allow other threads to acquire references to the device now
1783 * that the driver's attach function is done. 1783 * that the driver's attach function is done.
1784 */ 1784 */
1785 mutex_enter(&config_misc_lock); 1785 mutex_enter(&config_misc_lock);
1786 KASSERT(dev->dv_attaching == curlwp); 1786 KASSERT(dev->dv_attaching == curlwp);
1787 dev->dv_attaching = NULL; 1787 dev->dv_attaching = NULL;
1788 cv_broadcast(&config_misc_cv); 1788 cv_broadcast(&config_misc_cv);
1789 mutex_exit(&config_misc_lock); 1789 mutex_exit(&config_misc_lock);
1790 1790
1791 /* 1791 /*
1792 * Synchronous parts of attach are done. Allow detach, unless 1792 * Synchronous parts of attach are done. Allow detach, unless
1793 * the driver's attach function scheduled deferred actions. 1793 * the driver's attach function scheduled deferred actions.
1794 */ 1794 */
1795 config_pending_decr(dev); 1795 config_pending_decr(dev);
1796 1796
1797 mutex_enter(&config_misc_lock); 1797 mutex_enter(&config_misc_lock);
1798 deferred = (dev->dv_pending != 0); 1798 deferred = (dev->dv_pending != 0);
1799 mutex_exit(&config_misc_lock); 1799 mutex_exit(&config_misc_lock);
1800 1800
1801 if (!deferred && !device_pmf_is_registered(dev)) 1801 if (!deferred && !device_pmf_is_registered(dev))
1802 aprint_debug_dev(dev, 1802 aprint_debug_dev(dev,
1803 "WARNING: power management not supported\n"); 1803 "WARNING: power management not supported\n");
1804 1804
1805 config_process_deferred(&deferred_config_queue, dev); 1805 config_process_deferred(&deferred_config_queue, dev);
1806 1806
1807 device_register_post_config(dev, aux); 1807 device_register_post_config(dev, aux);
1808 rnd_add_uint32(&rnd_autoconf_source, 0); 1808 rnd_add_uint32(&rnd_autoconf_source, 0);
1809 return dev; 1809 return dev;
1810} 1810}
1811 1811
1812device_t 1812device_t
1813config_attach(device_t parent, cfdata_t cf, void *aux, cfprint_t print, 1813config_attach(device_t parent, cfdata_t cf, void *aux, cfprint_t print,
1814 const struct cfargs *cfargs) 1814 const struct cfargs *cfargs)
1815{ 1815{
1816 struct cfargs_internal store; 1816 struct cfargs_internal store;
1817 1817
1818 KASSERT(KERNEL_LOCKED_P()); 1818 KASSERT(KERNEL_LOCKED_P());
1819 1819
1820 return config_attach_internal(parent, cf, aux, print, 1820 return config_attach_internal(parent, cf, aux, print,
1821 cfargs_canonicalize(cfargs, &store)); 1821 cfargs_canonicalize(cfargs, &store));
1822} 1822}
1823 1823
1824/* 1824/*
1825 * As above, but for pseudo-devices. Pseudo-devices attached in this 1825 * As above, but for pseudo-devices. Pseudo-devices attached in this
1826 * way are silently inserted into the device tree, and their children 1826 * way are silently inserted into the device tree, and their children
1827 * attached. 1827 * attached.
1828 * 1828 *
1829 * Note that because pseudo-devices are attached silently, any information 1829 * Note that because pseudo-devices are attached silently, any information
1830 * the attach routine wishes to print should be prefixed with the device 1830 * the attach routine wishes to print should be prefixed with the device
1831 * name by the attach routine. 1831 * name by the attach routine.
1832 */ 1832 */
1833device_t 1833device_t
1834config_attach_pseudo(cfdata_t cf) 1834config_attach_pseudo(cfdata_t cf)
1835{ 1835{
1836 device_t dev; 1836 device_t dev;
1837 1837
1838 KERNEL_LOCK(1, NULL); 1838 KERNEL_LOCK(1, NULL);
1839 1839
1840 struct cfargs_internal args = { }; 1840 struct cfargs_internal args = { };
1841 dev = config_devalloc(ROOT, cf, &args); 1841 dev = config_devalloc(ROOT, cf, &args);
1842 if (!dev) 1842 if (!dev)
1843 goto out; 1843 goto out;
1844 1844
1845 /* XXX mark busy in cfdata */ 1845 /* XXX mark busy in cfdata */
1846 1846
1847 if (cf->cf_fstate != FSTATE_STAR) { 1847 if (cf->cf_fstate != FSTATE_STAR) {
1848 KASSERT(cf->cf_fstate == FSTATE_NOTFOUND); 1848 KASSERT(cf->cf_fstate == FSTATE_NOTFOUND);
1849 cf->cf_fstate = FSTATE_FOUND; 1849 cf->cf_fstate = FSTATE_FOUND;
1850 } 1850 }
1851 1851
1852 config_devlink(dev); 1852 config_devlink(dev);
1853 1853
1854#if 0 /* XXXJRT not yet */ 1854#if 0 /* XXXJRT not yet */
1855 device_register(dev, NULL); /* like a root node */ 1855 device_register(dev, NULL); /* like a root node */
1856#endif 1856#endif
1857 1857
1858 /* Let userland know */ 1858 /* Let userland know */
1859 devmon_report_device(dev, true); 1859 devmon_report_device(dev, true);
1860 1860
1861 /* 1861 /*
1862 * Prevent detach until the driver's attach function, and all 1862 * Prevent detach until the driver's attach function, and all
1863 * deferred actions, have finished. 1863 * deferred actions, have finished.
1864 */ 1864 */
1865 config_pending_incr(dev); 1865 config_pending_incr(dev);
1866 1866
1867 /* Call the driver's attach function. */ 1867 /* Call the driver's attach function. */
1868 (*dev->dv_cfattach->ca_attach)(ROOT, dev, NULL); 1868 (*dev->dv_cfattach->ca_attach)(ROOT, dev, NULL);
1869 1869
1870 /* 1870 /*
1871 * Allow other threads to acquire references to the device now 1871 * Allow other threads to acquire references to the device now
1872 * that the driver's attach function is done. 1872 * that the driver's attach function is done.
1873 */ 1873 */
1874 mutex_enter(&config_misc_lock); 1874 mutex_enter(&config_misc_lock);
1875 KASSERT(dev->dv_attaching == curlwp); 1875 KASSERT(dev->dv_attaching == curlwp);
1876 dev->dv_attaching = NULL; 1876 dev->dv_attaching = NULL;
1877 cv_broadcast(&config_misc_cv); 1877 cv_broadcast(&config_misc_cv);
1878 mutex_exit(&config_misc_lock); 1878 mutex_exit(&config_misc_lock);
1879 1879
1880 /* 1880 /*
1881 * Synchronous parts of attach are done. Allow detach, unless 1881 * Synchronous parts of attach are done. Allow detach, unless
1882 * the driver's attach function scheduled deferred actions. 1882 * the driver's attach function scheduled deferred actions.
1883 */ 1883 */
1884 config_pending_decr(dev); 1884 config_pending_decr(dev);
1885 1885
1886 config_process_deferred(&deferred_config_queue, dev); 1886 config_process_deferred(&deferred_config_queue, dev);
1887 1887
1888out: KERNEL_UNLOCK_ONE(NULL); 1888out: KERNEL_UNLOCK_ONE(NULL);
1889 return dev; 1889 return dev;
1890} 1890}
1891 1891
1892/* 1892/*
1893 * Caller must hold alldevs_lock. 1893 * Caller must hold alldevs_lock.
1894 */ 1894 */
1895static void 1895static void
1896config_collect_garbage(struct devicelist *garbage) 1896config_collect_garbage(struct devicelist *garbage)
1897{ 1897{
1898 device_t dv; 1898 device_t dv;
1899 1899
1900 KASSERT(!cpu_intr_p()); 1900 KASSERT(!cpu_intr_p());
1901 KASSERT(!cpu_softintr_p()); 1901 KASSERT(!cpu_softintr_p());
1902 KASSERT(mutex_owned(&alldevs_lock)); 1902 KASSERT(mutex_owned(&alldevs_lock));
1903 1903
1904 while (alldevs_nwrite == 0 && alldevs_nread == 0 && alldevs_garbage) { 1904 while (alldevs_nwrite == 0 && alldevs_nread == 0 && alldevs_garbage) {
1905 TAILQ_FOREACH(dv, &alldevs, dv_list) { 1905 TAILQ_FOREACH(dv, &alldevs, dv_list) {
1906 if (dv->dv_del_gen != 0) 1906 if (dv->dv_del_gen != 0)
1907 break; 1907 break;
1908 } 1908 }
1909 if (dv == NULL) { 1909 if (dv == NULL) {
1910 alldevs_garbage = false; 1910 alldevs_garbage = false;
1911 break; 1911 break;
1912 } 1912 }
1913 config_devunlink(dv, garbage); 1913 config_devunlink(dv, garbage);
1914 } 1914 }
1915 KASSERT(mutex_owned(&alldevs_lock)); 1915 KASSERT(mutex_owned(&alldevs_lock));
1916} 1916}
1917 1917
1918static void 1918static void
1919config_dump_garbage(struct devicelist *garbage) 1919config_dump_garbage(struct devicelist *garbage)
1920{ 1920{
1921 device_t dv; 1921 device_t dv;
1922 1922
1923 while ((dv = TAILQ_FIRST(garbage)) != NULL) { 1923 while ((dv = TAILQ_FIRST(garbage)) != NULL) {
1924 TAILQ_REMOVE(garbage, dv, dv_list); 1924 TAILQ_REMOVE(garbage, dv, dv_list);
1925 config_devdelete(dv); 1925 config_devdelete(dv);
1926 } 1926 }
1927} 1927}
1928 1928
1929static int 1929static int
1930config_detach_enter(device_t dev) 1930config_detach_enter(device_t dev)
1931{ 1931{
1932 struct lwp *l __diagused; 1932 struct lwp *l __diagused;
1933 int error = 0; 1933 int error = 0;
1934 1934
1935 mutex_enter(&config_misc_lock); 1935 mutex_enter(&config_misc_lock);
1936 1936
1937 /* 1937 /*
1938 * Wait until attach has fully completed, and until any 1938 * Wait until attach has fully completed, and until any
1939 * concurrent detach (e.g., drvctl racing with USB event 1939 * concurrent detach (e.g., drvctl racing with USB event
1940 * thread) has completed. 1940 * thread) has completed.
1941 * 1941 *
1942 * Caller must hold alldevs_nread or alldevs_nwrite (e.g., via 1942 * Caller must hold alldevs_nread or alldevs_nwrite (e.g., via
1943 * deviter) to ensure the winner of the race doesn't free the 1943 * deviter) to ensure the winner of the race doesn't free the
1944 * device leading the loser of the race into use-after-free. 1944 * device leading the loser of the race into use-after-free.
1945 * 1945 *
1946 * XXX Not all callers do this! 1946 * XXX Not all callers do this!
1947 */ 1947 */
1948 while (dev->dv_pending || dev->dv_detaching) { 1948 while (dev->dv_pending || dev->dv_detaching) {
1949 KASSERTMSG(dev->dv_detaching != curlwp, 1949 KASSERTMSG(dev->dv_detaching != curlwp,
1950 "recursively detaching %s", device_xname(dev)); 1950 "recursively detaching %s", device_xname(dev));
1951 error = cv_wait_sig(&config_misc_cv, &config_misc_lock); 1951 error = cv_wait_sig(&config_misc_cv, &config_misc_lock);
1952 if (error) 1952 if (error)
1953 goto out; 1953 goto out;
1954 } 1954 }
1955 1955
1956 /* 1956 /*
1957 * Attach has completed, and no other concurrent detach is 1957 * Attach has completed, and no other concurrent detach is
1958 * running. Claim the device for detaching. This will cause 1958 * running. Claim the device for detaching. This will cause
1959 * all new attempts to acquire references to block. 1959 * all new attempts to acquire references to block.
1960 */ 1960 */
1961 KASSERTMSG((l = dev->dv_attaching) == NULL, 1961 KASSERTMSG((l = dev->dv_attaching) == NULL,
1962 "lwp %ld [%s] @ %p attaching %s", 1962 "lwp %ld [%s] @ %p attaching %s",
1963 (long)l->l_lid, (l->l_name ? l->l_name : l->l_proc->p_comm), l, 1963 (long)l->l_lid, (l->l_name ? l->l_name : l->l_proc->p_comm), l,
1964 device_xname(dev)); 1964 device_xname(dev));
1965 KASSERTMSG((l = dev->dv_detaching) == NULL, 1965 KASSERTMSG((l = dev->dv_detaching) == NULL,
1966 "lwp %ld [%s] @ %p detaching %s", 1966 "lwp %ld [%s] @ %p detaching %s",
1967 (long)l->l_lid, (l->l_name ? l->l_name : l->l_proc->p_comm), l, 1967 (long)l->l_lid, (l->l_name ? l->l_name : l->l_proc->p_comm), l,
1968 device_xname(dev)); 1968 device_xname(dev));
1969 dev->dv_detaching = curlwp; 1969 dev->dv_detaching = curlwp;
1970 1970
1971out: mutex_exit(&config_misc_lock); 1971out: mutex_exit(&config_misc_lock);
1972 return error; 1972 return error;
1973} 1973}
1974 1974
1975static void 1975static void
1976config_detach_exit(device_t dev) 1976config_detach_exit(device_t dev)
1977{ 1977{
1978 struct lwp *l __diagused; 1978 struct lwp *l __diagused;
1979 1979
1980 mutex_enter(&config_misc_lock); 1980 mutex_enter(&config_misc_lock);
1981 KASSERTMSG(dev->dv_detaching != NULL, "not detaching %s", 1981 KASSERTMSG(dev->dv_detaching != NULL, "not detaching %s",
1982 device_xname(dev)); 1982 device_xname(dev));
1983 KASSERTMSG((l = dev->dv_detaching) == curlwp, 1983 KASSERTMSG((l = dev->dv_detaching) == curlwp,
1984 "lwp %ld [%s] @ %p detaching %s", 1984 "lwp %ld [%s] @ %p detaching %s",
1985 (long)l->l_lid, (l->l_name ? l->l_name : l->l_proc->p_comm), l, 1985 (long)l->l_lid, (l->l_name ? l->l_name : l->l_proc->p_comm), l,
1986 device_xname(dev)); 1986 device_xname(dev));
1987 dev->dv_detaching = NULL; 1987 dev->dv_detaching = NULL;
1988 cv_broadcast(&config_misc_cv); 1988 cv_broadcast(&config_misc_cv);
1989 mutex_exit(&config_misc_lock); 1989 mutex_exit(&config_misc_lock);
1990} 1990}
1991 1991
1992/* 1992/*
1993 * Detach a device. Optionally forced (e.g. because of hardware 1993 * Detach a device. Optionally forced (e.g. because of hardware
1994 * removal) and quiet. Returns zero if successful, non-zero 1994 * removal) and quiet. Returns zero if successful, non-zero
1995 * (an error code) otherwise. 1995 * (an error code) otherwise.
1996 * 1996 *
1997 * Note that this code wants to be run from a process context, so 1997 * Note that this code wants to be run from a process context, so
1998 * that the detach can sleep to allow processes which have a device 1998 * that the detach can sleep to allow processes which have a device
1999 * open to run and unwind their stacks. 1999 * open to run and unwind their stacks.
2000 */ 2000 */
2001int 2001int
2002config_detach(device_t dev, int flags) 2002config_detach(device_t dev, int flags)
2003{ 2003{
2004 struct alldevs_foray af; 2004 struct alldevs_foray af;
2005 struct cftable *ct; 2005 struct cftable *ct;
2006 cfdata_t cf; 2006 cfdata_t cf;
2007 const struct cfattach *ca; 2007 const struct cfattach *ca;
2008 struct cfdriver *cd; 2008 struct cfdriver *cd;
2009 device_t d __diagused; 2009 device_t d __diagused;
2010 int rv = 0; 2010 int rv = 0;
2011 2011
2012 KERNEL_LOCK(1, NULL); 2012 KERNEL_LOCK(1, NULL);
2013 2013
2014 cf = dev->dv_cfdata; 2014 cf = dev->dv_cfdata;
2015 KASSERTMSG((cf == NULL || cf->cf_fstate == FSTATE_FOUND || 2015 KASSERTMSG((cf == NULL || cf->cf_fstate == FSTATE_FOUND ||
2016 cf->cf_fstate == FSTATE_STAR), 2016 cf->cf_fstate == FSTATE_STAR),
2017 "config_detach: %s: bad device fstate: %d", 2017 "config_detach: %s: bad device fstate: %d",
2018 device_xname(dev), cf ? cf->cf_fstate : -1); 2018 device_xname(dev), cf ? cf->cf_fstate : -1);
2019 2019
2020 cd = dev->dv_cfdriver; 2020 cd = dev->dv_cfdriver;
2021 KASSERT(cd != NULL); 2021 KASSERT(cd != NULL);
2022 2022
2023 ca = dev->dv_cfattach; 2023 ca = dev->dv_cfattach;
2024 KASSERT(ca != NULL); 2024 KASSERT(ca != NULL);
2025 2025
2026 /* 2026 /*
2027 * Only one detach at a time, please -- and not until fully 2027 * Only one detach at a time, please -- and not until fully
2028 * attached. 2028 * attached.
2029 */ 2029 */
2030 rv = config_detach_enter(dev); 2030 rv = config_detach_enter(dev);
2031 if (rv) { 2031 if (rv) {
2032 KERNEL_UNLOCK_ONE(NULL); 2032 KERNEL_UNLOCK_ONE(NULL);
2033 return rv; 2033 return rv;
2034 } 2034 }
2035 2035
2036 mutex_enter(&alldevs_lock); 2036 mutex_enter(&alldevs_lock);
2037 if (dev->dv_del_gen != 0) { 2037 if (dev->dv_del_gen != 0) {
2038 mutex_exit(&alldevs_lock); 2038 mutex_exit(&alldevs_lock);
2039#ifdef DIAGNOSTIC 2039#ifdef DIAGNOSTIC
2040 printf("%s: %s is already detached\n", __func__, 2040 printf("%s: %s is already detached\n", __func__,
2041 device_xname(dev)); 2041 device_xname(dev));
2042#endif /* DIAGNOSTIC */ 2042#endif /* DIAGNOSTIC */
2043 config_detach_exit(dev); 2043 config_detach_exit(dev);
2044 KERNEL_UNLOCK_ONE(NULL); 2044 KERNEL_UNLOCK_ONE(NULL);
2045 return ENOENT; 2045 return ENOENT;
2046 } 2046 }
2047 alldevs_nwrite++; 2047 alldevs_nwrite++;
2048 mutex_exit(&alldevs_lock); 2048 mutex_exit(&alldevs_lock);
2049 2049
2050 /* 2050 /*
2051 * Call the driver's .ca_detach function, unless it has none or 2051 * Call the driver's .ca_detach function, unless it has none or
2052 * we are skipping it because it's unforced shutdown time and 2052 * we are skipping it because it's unforced shutdown time and
2053 * the driver didn't ask to detach on shutdown. 2053 * the driver didn't ask to detach on shutdown.
2054 */ 2054 */
2055 if (!detachall && 2055 if (!detachall &&
2056 (flags & (DETACH_SHUTDOWN|DETACH_FORCE)) == DETACH_SHUTDOWN && 2056 (flags & (DETACH_SHUTDOWN|DETACH_FORCE)) == DETACH_SHUTDOWN &&
2057 (dev->dv_flags & DVF_DETACH_SHUTDOWN) == 0) { 2057 (dev->dv_flags & DVF_DETACH_SHUTDOWN) == 0) {
2058 rv = EOPNOTSUPP; 2058 rv = EOPNOTSUPP;
2059 } else if (ca->ca_detach != NULL) { 2059 } else if (ca->ca_detach != NULL) {
2060 rv = (*ca->ca_detach)(dev, flags); 2060 rv = (*ca->ca_detach)(dev, flags);
2061 } else 2061 } else
2062 rv = EOPNOTSUPP; 2062 rv = EOPNOTSUPP;
2063 2063
2064 KASSERTMSG(!dev->dv_detach_done, "%s detached twice, error=%d", 2064 KASSERTMSG(!dev->dv_detach_done, "%s detached twice, error=%d",
2065 device_xname(dev), rv); 2065 device_xname(dev), rv);
2066 2066
2067 /* 2067 /*
2068 * If it was not possible to detach the device, then we either 2068 * If it was not possible to detach the device, then we either
2069 * panic() (for the forced but failed case), or return an error. 2069 * panic() (for the forced but failed case), or return an error.
2070 */ 2070 */
2071 if (rv) { 2071 if (rv) {
2072 /* 2072 /*
2073 * Detach failed -- likely EOPNOTSUPP or EBUSY. Driver 2073 * Detach failed -- likely EOPNOTSUPP or EBUSY. Driver
2074 * must not have called config_detach_commit. 2074 * must not have called config_detach_commit.
2075 */ 2075 */
2076 KASSERTMSG(!dev->dv_detach_committed, 2076 KASSERTMSG(!dev->dv_detach_committed,
2077 "%s committed to detaching and then backed out, error=%d", 2077 "%s committed to detaching and then backed out, error=%d",
2078 device_xname(dev), rv); 2078 device_xname(dev), rv);
2079 if (flags & DETACH_FORCE) { 2079 if (flags & DETACH_FORCE) {
2080 panic("config_detach: forced detach of %s failed (%d)", 2080 panic("config_detach: forced detach of %s failed (%d)",
2081 device_xname(dev), rv); 2081 device_xname(dev), rv);
2082 } 2082 }
2083 goto out; 2083 goto out;
2084 } 2084 }
2085 2085
2086 /* 2086 /*
2087 * The device has now been successfully detached. 2087 * The device has now been successfully detached.
2088 */ 2088 */
2089 dev->dv_detach_done = true; 2089 dev->dv_detach_done = true;
2090 2090
2091 /* 2091 /*
2092 * If .ca_detach didn't commit to detach, then do that for it. 2092 * If .ca_detach didn't commit to detach, then do that for it.
2093 * This wakes any pending device_lookup_acquire calls so they 2093 * This wakes any pending device_lookup_acquire calls so they
2094 * will fail. 2094 * will fail.
2095 */ 2095 */
2096 config_detach_commit(dev); 2096 config_detach_commit(dev);
2097 2097
2098 /* 2098 /*
2099 * If it was possible to detach the device, ensure that the 2099 * If it was possible to detach the device, ensure that the
2100 * device is deactivated. 2100 * device is deactivated.
2101 */ 2101 */
2102 dev->dv_flags &= ~DVF_ACTIVE; /* XXXSMP */ 2102 dev->dv_flags &= ~DVF_ACTIVE; /* XXXSMP */
2103 2103
2104 /* 2104 /*
2105 * Wait for all device_lookup_acquire references -- mostly, for 2105 * Wait for all device_lookup_acquire references -- mostly, for
2106 * all attempts to open the device -- to drain. It is the 2106 * all attempts to open the device -- to drain. It is the
2107 * responsibility of .ca_detach to ensure anything with open 2107 * responsibility of .ca_detach to ensure anything with open
2108 * references will be interrupted and release them promptly, 2108 * references will be interrupted and release them promptly,
2109 * not block indefinitely. All new attempts to acquire 2109 * not block indefinitely. All new attempts to acquire
2110 * references will fail, as config_detach_commit has arranged 2110 * references will fail, as config_detach_commit has arranged
2111 * by now. 2111 * by now.
2112 */ 2112 */
2113 mutex_enter(&config_misc_lock); 2113 mutex_enter(&config_misc_lock);
2114 localcount_drain(dev->dv_localcount, 2114 localcount_drain(dev->dv_localcount,
2115 &config_misc_cv, &config_misc_lock); 2115 &config_misc_cv, &config_misc_lock);
2116 mutex_exit(&config_misc_lock); 2116 mutex_exit(&config_misc_lock);
2117 2117
2118 /* Let userland know */ 2118 /* Let userland know */
2119 devmon_report_device(dev, false); 2119 devmon_report_device(dev, false);
2120 2120
2121#ifdef DIAGNOSTIC 2121#ifdef DIAGNOSTIC
2122 /* 2122 /*
2123 * Sanity: If you're successfully detached, you should have no 2123 * Sanity: If you're successfully detached, you should have no
2124 * children. (Note that because children must be attached 2124 * children. (Note that because children must be attached
2125 * after parents, we only need to search the latter part of 2125 * after parents, we only need to search the latter part of
2126 * the list.) 2126 * the list.)
2127 */ 2127 */
2128 mutex_enter(&alldevs_lock); 2128 mutex_enter(&alldevs_lock);
2129 for (d = TAILQ_NEXT(dev, dv_list); d != NULL; 2129 for (d = TAILQ_NEXT(dev, dv_list); d != NULL;
2130 d = TAILQ_NEXT(d, dv_list)) { 2130 d = TAILQ_NEXT(d, dv_list)) {
2131 if (d->dv_parent == dev && d->dv_del_gen == 0) { 2131 if (d->dv_parent == dev && d->dv_del_gen == 0) {
2132 printf("config_detach: detached device %s" 2132 printf("config_detach: detached device %s"
2133 " has children %s\n", device_xname(dev), 2133 " has children %s\n", device_xname(dev),
2134 device_xname(d)); 2134 device_xname(d));
2135 panic("config_detach"); 2135 panic("config_detach");
2136 } 2136 }
2137 } 2137 }
2138 mutex_exit(&alldevs_lock); 2138 mutex_exit(&alldevs_lock);
2139#endif 2139#endif
2140 2140
2141 /* notify the parent that the child is gone */ 2141 /* notify the parent that the child is gone */
2142 if (dev->dv_parent) { 2142 if (dev->dv_parent) {
2143 device_t p = dev->dv_parent; 2143 device_t p = dev->dv_parent;
2144 if (p->dv_cfattach->ca_childdetached) 2144 if (p->dv_cfattach->ca_childdetached)
2145 (*p->dv_cfattach->ca_childdetached)(p, dev); 2145 (*p->dv_cfattach->ca_childdetached)(p, dev);
2146 } 2146 }
2147 2147
2148 /* 2148 /*
2149 * Mark cfdata to show that the unit can be reused, if possible. 2149 * Mark cfdata to show that the unit can be reused, if possible.
2150 */ 2150 */
2151 TAILQ_FOREACH(ct, &allcftables, ct_list) { 2151 TAILQ_FOREACH(ct, &allcftables, ct_list) {
2152 for (cf = ct->ct_cfdata; cf->cf_name; cf++) { 2152 for (cf = ct->ct_cfdata; cf->cf_name; cf++) {
2153 if (STREQ(cf->cf_name, cd->cd_name)) { 2153 if (STREQ(cf->cf_name, cd->cd_name)) {
2154 if (cf->cf_fstate == FSTATE_FOUND && 2154 if (cf->cf_fstate == FSTATE_FOUND &&
2155 cf->cf_unit == dev->dv_unit) 2155 cf->cf_unit == dev->dv_unit)
2156 cf->cf_fstate = FSTATE_NOTFOUND; 2156 cf->cf_fstate = FSTATE_NOTFOUND;
2157 } 2157 }
2158 } 2158 }
2159 } 2159 }
2160 2160
2161 if (dev->dv_cfdata != NULL && (flags & DETACH_QUIET) == 0) 2161 if (dev->dv_cfdata != NULL && (flags & DETACH_QUIET) == 0)
2162 aprint_normal_dev(dev, "detached\n"); 2162 aprint_normal_dev(dev, "detached\n");
2163 2163
2164out: 2164out:
2165 config_detach_exit(dev); 2165 config_detach_exit(dev);
2166 2166
2167 config_alldevs_enter(&af); 2167 config_alldevs_enter(&af);
2168 KASSERT(alldevs_nwrite != 0); 2168 KASSERT(alldevs_nwrite != 0);
2169 --alldevs_nwrite; 2169 --alldevs_nwrite;
2170 if (rv == 0 && dev->dv_del_gen == 0) { 2170 if (rv == 0 && dev->dv_del_gen == 0) {
2171 if (alldevs_nwrite == 0 && alldevs_nread == 0) 2171 if (alldevs_nwrite == 0 && alldevs_nread == 0)
2172 config_devunlink(dev, &af.af_garbage); 2172 config_devunlink(dev, &af.af_garbage);
2173 else { 2173 else {
2174 dev->dv_del_gen = alldevs_gen; 2174 dev->dv_del_gen = alldevs_gen;
2175 alldevs_garbage = true; 2175 alldevs_garbage = true;
2176 } 2176 }
2177 } 2177 }
2178 config_alldevs_exit(&af); 2178 config_alldevs_exit(&af);
2179 2179
2180 KERNEL_UNLOCK_ONE(NULL); 2180 KERNEL_UNLOCK_ONE(NULL);
2181 2181
2182 return rv; 2182 return rv;
2183} 2183}
2184 2184
2185/* 2185/*
2186 * config_detach_commit(dev) 2186 * config_detach_commit(dev)
2187 * 2187 *
2188 * Issued by a driver's .ca_detach routine to notify anyone 2188 * Issued by a driver's .ca_detach routine to notify anyone
2189 * waiting in device_lookup_acquire that the driver is committed 2189 * waiting in device_lookup_acquire that the driver is committed
2190 * to detaching the device, which allows device_lookup_acquire to 2190 * to detaching the device, which allows device_lookup_acquire to
2191 * wake up and fail immediately. 2191 * wake up and fail immediately.
2192 * 2192 *
2193 * Safe to call multiple times -- idempotent. Must be called 2193 * Safe to call multiple times -- idempotent. Must be called
2194 * during config_detach_enter/exit. Safe to use with 2194 * during config_detach_enter/exit. Safe to use with
2195 * device_lookup because the device is not actually removed from 2195 * device_lookup because the device is not actually removed from
2196 * the table until after config_detach_exit. 2196 * the table until after config_detach_exit.
2197 */ 2197 */
2198void 2198void
2199config_detach_commit(device_t dev) 2199config_detach_commit(device_t dev)
2200{ 2200{
2201 struct lwp *l __diagused; 2201 struct lwp *l __diagused;
2202 2202
2203 mutex_enter(&config_misc_lock); 2203 mutex_enter(&config_misc_lock);
2204 KASSERTMSG(dev->dv_detaching != NULL, "not detaching %s", 2204 KASSERTMSG(dev->dv_detaching != NULL, "not detaching %s",
2205 device_xname(dev)); 2205 device_xname(dev));
2206 KASSERTMSG((l = dev->dv_detaching) == curlwp, 2206 KASSERTMSG((l = dev->dv_detaching) == curlwp,
2207 "lwp %ld [%s] @ %p detaching %s", 2207 "lwp %ld [%s] @ %p detaching %s",
2208 (long)l->l_lid, (l->l_name ? l->l_name : l->l_proc->p_comm), l, 2208 (long)l->l_lid, (l->l_name ? l->l_name : l->l_proc->p_comm), l,
2209 device_xname(dev)); 2209 device_xname(dev));
2210 dev->dv_detach_committed = true; 2210 dev->dv_detach_committed = true;
2211 cv_broadcast(&config_misc_cv); 2211 cv_broadcast(&config_misc_cv);
2212 mutex_exit(&config_misc_lock); 2212 mutex_exit(&config_misc_lock);
2213} 2213}
2214 2214
2215int 2215int
2216config_detach_children(device_t parent, int flags) 2216config_detach_children(device_t parent, int flags)
2217{ 2217{
2218 device_t dv; 2218 device_t dv;
2219 deviter_t di; 2219 deviter_t di;
2220 int error = 0; 2220 int error = 0;
2221 2221
2222 KASSERT(KERNEL_LOCKED_P()); 2222 KASSERT(KERNEL_LOCKED_P());
2223 2223
2224 for (dv = deviter_first(&di, DEVITER_F_RW); dv != NULL; 2224 for (dv = deviter_first(&di, DEVITER_F_RW); dv != NULL;
2225 dv = deviter_next(&di)) { 2225 dv = deviter_next(&di)) {
2226 if (device_parent(dv) != parent) 2226 if (device_parent(dv) != parent)
2227 continue; 2227 continue;
2228 if ((error = config_detach(dv, flags)) != 0) 2228 if ((error = config_detach(dv, flags)) != 0)
2229 break; 2229 break;
2230 } 2230 }
2231 deviter_release(&di); 2231 deviter_release(&di);
2232 return error; 2232 return error;
2233} 2233}
2234 2234
2235device_t 2235device_t
2236shutdown_first(struct shutdown_state *s) 2236shutdown_first(struct shutdown_state *s)
2237{ 2237{
2238 if (!s->initialized) { 2238 if (!s->initialized) {
2239 deviter_init(&s->di, DEVITER_F_SHUTDOWN|DEVITER_F_LEAVES_FIRST); 2239 deviter_init(&s->di, DEVITER_F_SHUTDOWN|DEVITER_F_LEAVES_FIRST);
2240 s->initialized = true; 2240 s->initialized = true;
2241 } 2241 }
2242 return shutdown_next(s); 2242 return shutdown_next(s);
2243} 2243}
2244 2244
2245device_t 2245device_t
2246shutdown_next(struct shutdown_state *s) 2246shutdown_next(struct shutdown_state *s)
2247{ 2247{
2248 device_t dv; 2248 device_t dv;
2249 2249
2250 while ((dv = deviter_next(&s->di)) != NULL && !device_is_active(dv)) 2250 while ((dv = deviter_next(&s->di)) != NULL && !device_is_active(dv))
2251 ; 2251 ;
2252 2252
2253 if (dv == NULL) 2253 if (dv == NULL)
2254 s->initialized = false; 2254 s->initialized = false;
2255 2255
2256 return dv; 2256 return dv;
2257} 2257}
2258 2258
2259bool 2259bool
2260config_detach_all(int how) 2260config_detach_all(int how)
2261{ 2261{
2262 static struct shutdown_state s; 2262 static struct shutdown_state s;
2263 device_t curdev; 2263 device_t curdev;
2264 bool progress = false; 2264 bool progress = false;
2265 int flags; 2265 int flags;
2266 2266
2267 KERNEL_LOCK(1, NULL); 2267 KERNEL_LOCK(1, NULL);
2268 2268
2269 if ((how & (RB_NOSYNC|RB_DUMP)) != 0) 2269 if ((how & (RB_NOSYNC|RB_DUMP)) != 0)
2270 goto out; 2270 goto out;
2271 2271
2272 if ((how & RB_POWERDOWN) == RB_POWERDOWN) 2272 if ((how & RB_POWERDOWN) == RB_POWERDOWN)
2273 flags = DETACH_SHUTDOWN | DETACH_POWEROFF; 2273 flags = DETACH_SHUTDOWN | DETACH_POWEROFF;
2274 else 2274 else
2275 flags = DETACH_SHUTDOWN; 2275 flags = DETACH_SHUTDOWN;
2276 2276
2277 for (curdev = shutdown_first(&s); curdev != NULL; 2277 for (curdev = shutdown_first(&s); curdev != NULL;
2278 curdev = shutdown_next(&s)) { 2278 curdev = shutdown_next(&s)) {
2279 aprint_debug(" detaching %s, ", device_xname(curdev)); 2279 aprint_debug(" detaching %s, ", device_xname(curdev));
2280 if (config_detach(curdev, flags) == 0) { 2280 if (config_detach(curdev, flags) == 0) {
2281 progress = true; 2281 progress = true;
2282 aprint_debug("success."); 2282 aprint_debug("success.");
2283 } else 2283 } else
2284 aprint_debug("failed."); 2284 aprint_debug("failed.");
2285 } 2285 }
2286 2286
2287out: KERNEL_UNLOCK_ONE(NULL); 2287out: KERNEL_UNLOCK_ONE(NULL);
2288 return progress; 2288 return progress;
2289} 2289}
2290 2290
2291static bool 2291static bool
2292device_is_ancestor_of(device_t ancestor, device_t descendant) 2292device_is_ancestor_of(device_t ancestor, device_t descendant)
2293{ 2293{
2294 device_t dv; 2294 device_t dv;
2295 2295
2296 for (dv = descendant; dv != NULL; dv = device_parent(dv)) { 2296 for (dv = descendant; dv != NULL; dv = device_parent(dv)) {
2297 if (device_parent(dv) == ancestor) 2297 if (device_parent(dv) == ancestor)
2298 return true; 2298 return true;
2299 } 2299 }
2300 return false; 2300 return false;
2301} 2301}
2302 2302
2303int 2303int
2304config_deactivate(device_t dev) 2304config_deactivate(device_t dev)
2305{ 2305{
2306 deviter_t di; 2306 deviter_t di;
2307 const struct cfattach *ca; 2307 const struct cfattach *ca;
2308 device_t descendant; 2308 device_t descendant;
2309 int s, rv = 0, oflags; 2309 int s, rv = 0, oflags;
2310 2310
2311 for (descendant = deviter_first(&di, DEVITER_F_ROOT_FIRST); 2311 for (descendant = deviter_first(&di, DEVITER_F_ROOT_FIRST);
2312 descendant != NULL; 2312 descendant != NULL;
2313 descendant = deviter_next(&di)) { 2313 descendant = deviter_next(&di)) {
2314 if (dev != descendant && 2314 if (dev != descendant &&
2315 !device_is_ancestor_of(dev, descendant)) 2315 !device_is_ancestor_of(dev, descendant))
2316 continue; 2316 continue;
2317 2317
2318 if ((descendant->dv_flags & DVF_ACTIVE) == 0) 2318 if ((descendant->dv_flags & DVF_ACTIVE) == 0)
2319 continue; 2319 continue;
2320 2320
2321 ca = descendant->dv_cfattach; 2321 ca = descendant->dv_cfattach;
2322 oflags = descendant->dv_flags; 2322 oflags = descendant->dv_flags;
2323 2323
2324 descendant->dv_flags &= ~DVF_ACTIVE; 2324 descendant->dv_flags &= ~DVF_ACTIVE;
2325 if (ca->ca_activate == NULL) 2325 if (ca->ca_activate == NULL)
2326 continue; 2326 continue;
2327 s = splhigh(); 2327 s = splhigh();
2328 rv = (*ca->ca_activate)(descendant, DVACT_DEACTIVATE); 2328 rv = (*ca->ca_activate)(descendant, DVACT_DEACTIVATE);
2329 splx(s); 2329 splx(s);
2330 if (rv != 0) 2330 if (rv != 0)
2331 descendant->dv_flags = oflags; 2331 descendant->dv_flags = oflags;
2332 } 2332 }
2333 deviter_release(&di); 2333 deviter_release(&di);
2334 return rv; 2334 return rv;
2335} 2335}
2336 2336
2337/* 2337/*
2338 * Defer the configuration of the specified device until all 2338 * Defer the configuration of the specified device until all
2339 * of its parent's devices have been attached. 2339 * of its parent's devices have been attached.
2340 */ 2340 */
2341void 2341void
2342config_defer(device_t dev, void (*func)(device_t)) 2342config_defer(device_t dev, void (*func)(device_t))
2343{ 2343{
2344 struct deferred_config *dc; 2344 struct deferred_config *dc;
2345 2345
2346 if (dev->dv_parent == NULL) 2346 if (dev->dv_parent == NULL)
2347 panic("config_defer: can't defer config of a root device"); 2347 panic("config_defer: can't defer config of a root device");
2348 2348
2349 dc = kmem_alloc(sizeof(*dc), KM_SLEEP); 2349 dc = kmem_alloc(sizeof(*dc), KM_SLEEP);
2350 2350
2351 config_pending_incr(dev); 2351 config_pending_incr(dev);
2352 2352
2353 mutex_enter(&config_misc_lock); 2353 mutex_enter(&config_misc_lock);
2354#ifdef DIAGNOSTIC 2354#ifdef DIAGNOSTIC
2355 struct deferred_config *odc; 2355 struct deferred_config *odc;
2356 TAILQ_FOREACH(odc, &deferred_config_queue, dc_queue) { 2356 TAILQ_FOREACH(odc, &deferred_config_queue, dc_queue) {
2357 if (odc->dc_dev == dev) 2357 if (odc->dc_dev == dev)
2358 panic("config_defer: deferred twice"); 2358 panic("config_defer: deferred twice");
2359 } 2359 }