subr_autoconf.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  1. /* $OpenBSD: subr_autoconf.c,v 1.87 2015/03/14 03:38:50 jsg Exp $ */
  2. /* $NetBSD: subr_autoconf.c,v 1.21 1996/04/04 06:06:18 cgd Exp $ */
  3. /*
  4. * Copyright (c) 1992, 1993
  5. * The Regents of the University of California. All rights reserved.
  6. *
  7. * This software was developed by the Computer Systems Engineering group
  8. * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
  9. * contributed to Berkeley.
  10. *
  11. * All advertising materials mentioning features or use of this software
  12. * must display the following acknowledgement:
  13. * This product includes software developed by the University of
  14. * California, Lawrence Berkeley Laboratories.
  15. *
  16. * Redistribution and use in source and binary forms, with or without
  17. * modification, are permitted provided that the following conditions
  18. * are met:
  19. * 1. Redistributions of source code must retain the above copyright
  20. * notice, this list of conditions and the following disclaimer.
  21. * 2. Redistributions in binary form must reproduce the above copyright
  22. * notice, this list of conditions and the following disclaimer in the
  23. * documentation and/or other materials provided with the distribution.
  24. * 3. Neither the name of the University nor the names of its contributors
  25. * may be used to endorse or promote products derived from this software
  26. * without specific prior written permission.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  29. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  32. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  37. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  38. * SUCH DAMAGE.
  39. *
  40. * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp (LBL)
  41. *
  42. * @(#)subr_autoconf.c 8.1 (Berkeley) 6/10/93
  43. */
  44. #include <sys/param.h>
  45. #include <sys/device.h>
  46. #include <sys/hotplug.h>
  47. #include <sys/malloc.h>
  48. #include <sys/systm.h>
  49. #include <sys/queue.h>
  50. #include <sys/mutex.h>
  51. #include <sys/atomic.h>
  52. #include "hotplug.h"
  53. #include "mpath.h"
  54. /*
  55. * Autoconfiguration subroutines.
  56. */
  57. /*
  58. * ioconf.c exports exactly two names: cfdata and cfroots. All system
  59. * devices and drivers are found via these tables.
  60. */
  61. extern short cfroots[];
  62. #define ROOT ((struct device *)NULL)
  63. struct matchinfo {
  64. cfmatch_t fn;
  65. struct device *parent;
  66. void *match, *aux;
  67. int indirect, pri;
  68. };
  69. #ifndef AUTOCONF_VERBOSE
  70. #define AUTOCONF_VERBOSE 0
  71. #endif /* AUTOCONF_VERBOSE */
  72. int autoconf_verbose = AUTOCONF_VERBOSE; /* trace probe calls */
  73. static void mapply(struct matchinfo *, struct cfdata *);
  74. struct deferred_config {
  75. TAILQ_ENTRY(deferred_config) dc_queue;
  76. struct device *dc_dev;
  77. void (*dc_func)(struct device *);
  78. };
  79. TAILQ_HEAD(, deferred_config) deferred_config_queue;
  80. void config_process_deferred_children(struct device *);
  81. struct devicelist alldevs; /* list of all devices */
  82. volatile int config_pending; /* semaphore for mountroot */
  83. struct mutex autoconf_attdet_mtx = MUTEX_INITIALIZER(IPL_HIGH);
  84. /*
  85. * If > 0, devices are being attached and any thread which tries to
  86. * detach will sleep; if < 0 devices are being detached and any
  87. * thread which tries to attach will sleep.
  88. */
  89. int autoconf_attdet;
  90. /*
  91. * Initialize autoconfiguration data structures. This occurs before console
  92. * initialization as that might require use of this subsystem. Furthermore
  93. * this means that malloc et al. isn't yet available.
  94. */
  95. void
  96. config_init(void)
  97. {
  98. TAILQ_INIT(&deferred_config_queue);
  99. TAILQ_INIT(&alldevs);
  100. }
  101. /*
  102. * Apply the matching function and choose the best. This is used
  103. * a few times and we want to keep the code small.
  104. */
  105. void
  106. mapply(struct matchinfo *m, struct cfdata *cf)
  107. {
  108. int pri;
  109. void *match;
  110. if (m->indirect)
  111. match = config_make_softc(m->parent, cf);
  112. else
  113. match = cf;
  114. if (autoconf_verbose) {
  115. printf(">>> probing for %s", cf->cf_driver->cd_name);
  116. if (cf->cf_fstate == FSTATE_STAR)
  117. printf("*\n");
  118. else
  119. printf("%d\n", cf->cf_unit);
  120. }
  121. if (m->fn != NULL)
  122. pri = (*m->fn)(m->parent, match, m->aux);
  123. else {
  124. if (cf->cf_attach->ca_match == NULL) {
  125. panic("mapply: no match function for '%s' device",
  126. cf->cf_driver->cd_name);
  127. }
  128. pri = (*cf->cf_attach->ca_match)(m->parent, match, m->aux);
  129. }
  130. if (autoconf_verbose)
  131. printf(">>> %s probe returned %d\n", cf->cf_driver->cd_name,
  132. pri);
  133. if (pri > m->pri) {
  134. if (m->indirect && m->match)
  135. free(m->match, M_DEVBUF, 0);
  136. m->match = match;
  137. m->pri = pri;
  138. } else {
  139. if (m->indirect)
  140. free(match, M_DEVBUF, 0);
  141. }
  142. }
  143. /*
  144. * Iterate over all potential children of some device, calling the given
  145. * function (default being the child's match function) for each one.
  146. * Nonzero returns are matches; the highest value returned is considered
  147. * the best match. Return the `found child' if we got a match, or NULL
  148. * otherwise. The `aux' pointer is simply passed on through.
  149. *
  150. * Note that this function is designed so that it can be used to apply
  151. * an arbitrary function to all potential children (its return value
  152. * can be ignored).
  153. */
  154. void *
  155. config_search(cfmatch_t fn, struct device *parent, void *aux)
  156. {
  157. struct cfdata *cf;
  158. short *p;
  159. struct matchinfo m;
  160. m.fn = fn;
  161. m.parent = parent;
  162. m.match = NULL;
  163. m.aux = aux;
  164. m.indirect = parent && parent->dv_cfdata->cf_driver->cd_indirect;
  165. m.pri = 0;
  166. for (cf = cfdata; cf->cf_driver; cf++) {
  167. /*
  168. * Skip cf if no longer eligible, otherwise scan
  169. * through parents for one matching `parent',
  170. * and try match function.
  171. */
  172. if (cf->cf_fstate == FSTATE_FOUND)
  173. continue;
  174. if (cf->cf_fstate == FSTATE_DNOTFOUND ||
  175. cf->cf_fstate == FSTATE_DSTAR)
  176. continue;
  177. for (p = cf->cf_parents; *p >= 0; p++)
  178. if (parent->dv_cfdata == &cfdata[*p])
  179. mapply(&m, cf);
  180. }
  181. if (autoconf_verbose) {
  182. if (m.match) {
  183. if (m.indirect)
  184. cf = ((struct device *)m.match)->dv_cfdata;
  185. else
  186. cf = (struct cfdata *)m.match;
  187. printf(">>> %s probe won\n",
  188. cf->cf_driver->cd_name);
  189. } else
  190. printf(">>> no winning probe\n");
  191. }
  192. return (m.match);
  193. }
  194. /*
  195. * Iterate over all potential children of some device, calling the given
  196. * function for each one.
  197. *
  198. * Note that this function is designed so that it can be used to apply
  199. * an arbitrary function to all potential children (its return value
  200. * can be ignored).
  201. */
  202. void
  203. config_scan(cfscan_t fn, struct device *parent)
  204. {
  205. struct cfdata *cf;
  206. short *p;
  207. void *match;
  208. int indirect;
  209. indirect = parent && parent->dv_cfdata->cf_driver->cd_indirect;
  210. for (cf = cfdata; cf->cf_driver; cf++) {
  211. /*
  212. * Skip cf if no longer eligible, otherwise scan
  213. * through parents for one matching `parent',
  214. * and try match function.
  215. */
  216. if (cf->cf_fstate == FSTATE_FOUND)
  217. continue;
  218. if (cf->cf_fstate == FSTATE_DNOTFOUND ||
  219. cf->cf_fstate == FSTATE_DSTAR)
  220. continue;
  221. for (p = cf->cf_parents; *p >= 0; p++)
  222. if (parent->dv_cfdata == &cfdata[*p]) {
  223. match = indirect?
  224. config_make_softc(parent, cf) :
  225. (void *)cf;
  226. (*fn)(parent, match);
  227. }
  228. }
  229. }
  230. /*
  231. * Find the given root device.
  232. * This is much like config_search, but there is no parent.
  233. */
  234. void *
  235. config_rootsearch(cfmatch_t fn, char *rootname, void *aux)
  236. {
  237. struct cfdata *cf;
  238. short *p;
  239. struct matchinfo m;
  240. m.fn = fn;
  241. m.parent = ROOT;
  242. m.match = NULL;
  243. m.aux = aux;
  244. m.indirect = 0;
  245. m.pri = 0;
  246. /*
  247. * Look at root entries for matching name. We do not bother
  248. * with found-state here since only one instance of each possible
  249. * root child should ever be searched.
  250. */
  251. for (p = cfroots; *p >= 0; p++) {
  252. cf = &cfdata[*p];
  253. if (cf->cf_fstate == FSTATE_DNOTFOUND ||
  254. cf->cf_fstate == FSTATE_DSTAR)
  255. continue;
  256. if (strcmp(cf->cf_driver->cd_name, rootname) == 0)
  257. mapply(&m, cf);
  258. }
  259. return (m.match);
  260. }
  261. const char *msgs[3] = { "", " not configured\n", " unsupported\n" };
  262. /*
  263. * The given `aux' argument describes a device that has been found
  264. * on the given parent, but not necessarily configured. Locate the
  265. * configuration data for that device (using the submatch function
  266. * provided, or using candidates' cd_match configuration driver
  267. * functions) and attach it, and return true. If the device was
  268. * not configured, call the given `print' function and return 0.
  269. */
  270. struct device *
  271. config_found_sm(struct device *parent, void *aux, cfprint_t print,
  272. cfmatch_t submatch)
  273. {
  274. void *match;
  275. if ((match = config_search(submatch, parent, aux)) != NULL)
  276. return (config_attach(parent, match, aux, print));
  277. if (print)
  278. printf("%s", msgs[(*print)(aux, parent->dv_xname)]);
  279. return (NULL);
  280. }
  281. /*
  282. * As above, but for root devices.
  283. */
  284. struct device *
  285. config_rootfound(char *rootname, void *aux)
  286. {
  287. void *match;
  288. if ((match = config_rootsearch((cfmatch_t)NULL, rootname, aux)) != NULL)
  289. return (config_attach(ROOT, match, aux, (cfprint_t)NULL));
  290. printf("root device %s not configured\n", rootname);
  291. return (NULL);
  292. }
  293. /*
  294. * Attach a found device. Allocates memory for device variables.
  295. */
  296. struct device *
  297. config_attach(struct device *parent, void *match, void *aux, cfprint_t print)
  298. {
  299. struct cfdata *cf;
  300. struct device *dev;
  301. struct cfdriver *cd;
  302. struct cfattach *ca;
  303. mtx_enter(&autoconf_attdet_mtx);
  304. while (autoconf_attdet < 0)
  305. msleep(&autoconf_attdet, &autoconf_attdet_mtx,
  306. PWAIT, "autoconf", 0);
  307. autoconf_attdet++;
  308. mtx_leave(&autoconf_attdet_mtx);
  309. if (parent && parent->dv_cfdata->cf_driver->cd_indirect) {
  310. dev = match;
  311. cf = dev->dv_cfdata;
  312. } else {
  313. cf = match;
  314. dev = config_make_softc(parent, cf);
  315. }
  316. cd = cf->cf_driver;
  317. ca = cf->cf_attach;
  318. KASSERT(cd->cd_devs != NULL);
  319. KASSERT(dev->dv_unit < cd->cd_ndevs);
  320. KASSERT(cd->cd_devs[dev->dv_unit] == NULL);
  321. cd->cd_devs[dev->dv_unit] = dev;
  322. /*
  323. * If this is a "STAR" device and we used the last unit, prepare for
  324. * another one.
  325. */
  326. if (cf->cf_fstate == FSTATE_STAR) {
  327. if (dev->dv_unit == cf->cf_unit)
  328. cf->cf_unit++;
  329. } else
  330. cf->cf_fstate = FSTATE_FOUND;
  331. TAILQ_INSERT_TAIL(&alldevs, dev, dv_list);
  332. device_ref(dev);
  333. if (parent == ROOT)
  334. printf("%s at root", dev->dv_xname);
  335. else {
  336. printf("%s at %s", dev->dv_xname, parent->dv_xname);
  337. if (print)
  338. (void) (*print)(aux, (char *)0);
  339. }
  340. /*
  341. * Before attaching, clobber any unfound devices that are
  342. * otherwise identical, or bump the unit number on all starred
  343. * cfdata for this device.
  344. */
  345. for (cf = cfdata; cf->cf_driver; cf++) {
  346. if (cf->cf_driver == cd &&
  347. cf->cf_unit == dev->dv_unit) {
  348. if (cf->cf_fstate == FSTATE_NOTFOUND)
  349. cf->cf_fstate = FSTATE_FOUND;
  350. if (cf->cf_fstate == FSTATE_STAR)
  351. cf->cf_unit++;
  352. }
  353. }
  354. device_register(dev, aux);
  355. (*ca->ca_attach)(parent, dev, aux);
  356. config_process_deferred_children(dev);
  357. #if NHOTPLUG > 0
  358. if (!cold)
  359. hotplug_device_attach(cd->cd_class, dev->dv_xname);
  360. #endif
  361. mtx_enter(&autoconf_attdet_mtx);
  362. if (--autoconf_attdet == 0)
  363. wakeup(&autoconf_attdet);
  364. mtx_leave(&autoconf_attdet_mtx);
  365. return (dev);
  366. }
  367. struct device *
  368. config_make_softc(struct device *parent, struct cfdata *cf)
  369. {
  370. struct device *dev;
  371. struct cfdriver *cd;
  372. struct cfattach *ca;
  373. cd = cf->cf_driver;
  374. ca = cf->cf_attach;
  375. if (ca->ca_devsize < sizeof(struct device))
  376. panic("config_make_softc");
  377. /* get memory for all device vars */
  378. dev = malloc(ca->ca_devsize, M_DEVBUF, M_NOWAIT|M_ZERO);
  379. if (dev == NULL)
  380. panic("config_make_softc: allocation for device softc failed");
  381. dev->dv_class = cd->cd_class;
  382. dev->dv_cfdata = cf;
  383. dev->dv_flags = DVF_ACTIVE; /* always initially active */
  384. /* If this is a STAR device, search for a free unit number */
  385. if (cf->cf_fstate == FSTATE_STAR) {
  386. for (dev->dv_unit = cf->cf_starunit1;
  387. dev->dv_unit < cf->cf_unit; dev->dv_unit++)
  388. if (cd->cd_ndevs == 0 ||
  389. dev->dv_unit >= cd->cd_ndevs ||
  390. cd->cd_devs[dev->dv_unit] == NULL)
  391. break;
  392. } else
  393. dev->dv_unit = cf->cf_unit;
  394. /* Build the device name into dv_xname. */
  395. if (snprintf(dev->dv_xname, sizeof(dev->dv_xname), "%s%d",
  396. cd->cd_name, dev->dv_unit) >= sizeof(dev->dv_xname))
  397. panic("config_make_softc: device name too long");
  398. dev->dv_parent = parent;
  399. /* put this device in the devices array */
  400. if (dev->dv_unit >= cd->cd_ndevs) {
  401. /*
  402. * Need to expand the array.
  403. */
  404. int old = cd->cd_ndevs, new;
  405. void **nsp;
  406. if (old == 0)
  407. new = MINALLOCSIZE / sizeof(void *);
  408. else
  409. new = old * 2;
  410. while (new <= dev->dv_unit)
  411. new *= 2;
  412. cd->cd_ndevs = new;
  413. nsp = mallocarray(new, sizeof(void *), M_DEVBUF, M_NOWAIT|M_ZERO);
  414. if (nsp == NULL)
  415. panic("config_make_softc: %sing dev array",
  416. old != 0 ? "expand" : "creat");
  417. if (old != 0) {
  418. bcopy(cd->cd_devs, nsp, old * sizeof(void *));
  419. free(cd->cd_devs, M_DEVBUF, 0);
  420. }
  421. cd->cd_devs = nsp;
  422. }
  423. if (cd->cd_devs[dev->dv_unit])
  424. panic("config_make_softc: duplicate %s", dev->dv_xname);
  425. dev->dv_ref = 1;
  426. return (dev);
  427. }
  428. /*
  429. * Detach a device. Optionally forced (e.g. because of hardware
  430. * removal) and quiet. Returns zero if successful, non-zero
  431. * (an error code) otherwise.
  432. *
  433. * Note that this code wants to be run from a process context, so
  434. * that the detach can sleep to allow processes which have a device
  435. * open to run and unwind their stacks.
  436. */
  437. int
  438. config_detach(struct device *dev, int flags)
  439. {
  440. struct cfdata *cf;
  441. struct cfattach *ca;
  442. struct cfdriver *cd;
  443. int rv = 0, i;
  444. #ifdef DIAGNOSTIC
  445. struct device *d;
  446. #endif
  447. #if NHOTPLUG > 0
  448. char devname[16];
  449. #endif
  450. mtx_enter(&autoconf_attdet_mtx);
  451. while (autoconf_attdet > 0)
  452. msleep(&autoconf_attdet, &autoconf_attdet_mtx,
  453. PWAIT, "autoconf", 0);
  454. autoconf_attdet--;
  455. mtx_leave(&autoconf_attdet_mtx);
  456. #if NHOTPLUG > 0
  457. strlcpy(devname, dev->dv_xname, sizeof(devname));
  458. #endif
  459. cf = dev->dv_cfdata;
  460. #ifdef DIAGNOSTIC
  461. if (cf->cf_fstate != FSTATE_FOUND && cf->cf_fstate != FSTATE_STAR)
  462. panic("config_detach: bad device fstate");
  463. #endif
  464. ca = cf->cf_attach;
  465. cd = cf->cf_driver;
  466. /*
  467. * Ensure the device is deactivated. If the device has an
  468. * activation entry point and DVF_ACTIVE is still set, the
  469. * device is busy, and the detach fails.
  470. */
  471. rv = config_deactivate(dev);
  472. /*
  473. * Try to detach the device. If that's not possible, then
  474. * we either panic() (for the forced but failed case), or
  475. * return an error.
  476. */
  477. if (rv == 0) {
  478. if (ca->ca_detach != NULL)
  479. rv = (*ca->ca_detach)(dev, flags);
  480. else
  481. rv = EOPNOTSUPP;
  482. }
  483. if (rv != 0) {
  484. if ((flags & DETACH_FORCE) == 0)
  485. goto done;
  486. else
  487. panic("config_detach: forced detach of %s failed (%d)",
  488. dev->dv_xname, rv);
  489. }
  490. /*
  491. * The device has now been successfully detached.
  492. */
  493. #ifdef DIAGNOSTIC
  494. /*
  495. * Sanity: If you're successfully detached, you should have no
  496. * children. (Note that because children must be attached
  497. * after parents, we only need to search the latter part of
  498. * the list.)
  499. */
  500. i = 0;
  501. for (d = TAILQ_NEXT(dev, dv_list); d != NULL;
  502. d = TAILQ_NEXT(d, dv_list)) {
  503. if (d->dv_parent == dev) {
  504. printf("config_detach: %s attached at %s\n",
  505. d->dv_xname, dev->dv_xname);
  506. i = 1;
  507. }
  508. }
  509. if (i != 0)
  510. panic("config_detach: detached device (%s) has children",
  511. dev->dv_xname);
  512. #endif
  513. /*
  514. * Mark cfdata to show that the unit can be reused, if possible.
  515. * Note that we can only re-use a starred unit number if the unit
  516. * being detached had the last assigned unit number.
  517. */
  518. for (cf = cfdata; cf->cf_driver; cf++) {
  519. if (cf->cf_driver == cd) {
  520. if (cf->cf_fstate == FSTATE_FOUND &&
  521. cf->cf_unit == dev->dv_unit)
  522. cf->cf_fstate = FSTATE_NOTFOUND;
  523. if (cf->cf_fstate == FSTATE_STAR &&
  524. cf->cf_unit == dev->dv_unit + 1)
  525. cf->cf_unit--;
  526. }
  527. }
  528. /*
  529. * Unlink from device list.
  530. */
  531. TAILQ_REMOVE(&alldevs, dev, dv_list);
  532. device_unref(dev);
  533. /*
  534. * Remove from cfdriver's array, tell the world, and free softc.
  535. */
  536. cd->cd_devs[dev->dv_unit] = NULL;
  537. if ((flags & DETACH_QUIET) == 0)
  538. printf("%s detached\n", dev->dv_xname);
  539. device_unref(dev);
  540. /*
  541. * If the device now has no units in use, deallocate its softc array.
  542. */
  543. for (i = 0; i < cd->cd_ndevs; i++)
  544. if (cd->cd_devs[i] != NULL)
  545. break;
  546. if (i == cd->cd_ndevs) { /* nothing found; deallocate */
  547. free(cd->cd_devs, M_DEVBUF, 0);
  548. cd->cd_devs = NULL;
  549. cd->cd_ndevs = 0;
  550. cf->cf_unit = 0;
  551. }
  552. #if NHOTPLUG > 0
  553. if (!cold)
  554. hotplug_device_detach(cd->cd_class, devname);
  555. #endif
  556. /*
  557. * Return success.
  558. */
  559. done:
  560. mtx_enter(&autoconf_attdet_mtx);
  561. if (++autoconf_attdet == 0)
  562. wakeup(&autoconf_attdet);
  563. mtx_leave(&autoconf_attdet_mtx);
  564. return (rv);
  565. }
  566. int
  567. config_deactivate(struct device *dev)
  568. {
  569. int rv = 0, oflags = dev->dv_flags;
  570. if (dev->dv_flags & DVF_ACTIVE) {
  571. dev->dv_flags &= ~DVF_ACTIVE;
  572. rv = config_suspend(dev, DVACT_DEACTIVATE);
  573. if (rv)
  574. dev->dv_flags = oflags;
  575. }
  576. return (rv);
  577. }
  578. /*
  579. * Defer the configuration of the specified device until all
  580. * of its parent's devices have been attached.
  581. */
  582. void
  583. config_defer(struct device *dev, void (*func)(struct device *))
  584. {
  585. struct deferred_config *dc;
  586. if (dev->dv_parent == NULL)
  587. panic("config_defer: can't defer config of a root device");
  588. #ifdef DIAGNOSTIC
  589. for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL;
  590. dc = TAILQ_NEXT(dc, dc_queue)) {
  591. if (dc->dc_dev == dev)
  592. panic("config_defer: deferred twice");
  593. }
  594. #endif
  595. if ((dc = malloc(sizeof(*dc), M_DEVBUF, M_NOWAIT)) == NULL)
  596. panic("config_defer: can't allocate defer structure");
  597. dc->dc_dev = dev;
  598. dc->dc_func = func;
  599. TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue);
  600. config_pending_incr();
  601. }
  602. /*
  603. * Process the deferred configuration queue for a device.
  604. */
  605. void
  606. config_process_deferred_children(struct device *parent)
  607. {
  608. struct deferred_config *dc, *ndc;
  609. for (dc = TAILQ_FIRST(&deferred_config_queue);
  610. dc != NULL; dc = ndc) {
  611. ndc = TAILQ_NEXT(dc, dc_queue);
  612. if (dc->dc_dev->dv_parent == parent) {
  613. TAILQ_REMOVE(&deferred_config_queue, dc, dc_queue);
  614. (*dc->dc_func)(dc->dc_dev);
  615. free(dc, M_DEVBUF, 0);
  616. config_pending_decr();
  617. }
  618. }
  619. }
  620. /*
  621. * Manipulate the config_pending semaphore.
  622. */
  623. void
  624. config_pending_incr(void)
  625. {
  626. config_pending++;
  627. }
  628. void
  629. config_pending_decr(void)
  630. {
  631. #ifdef DIAGNOSTIC
  632. if (config_pending == 0)
  633. panic("config_pending_decr: config_pending == 0");
  634. #endif
  635. config_pending--;
  636. if (config_pending == 0)
  637. wakeup((void *)&config_pending);
  638. }
  639. int
  640. config_detach_children(struct device *parent, int flags)
  641. {
  642. struct device *dev, *next_dev;
  643. int rv = 0;
  644. /*
  645. * The config_detach routine may sleep, meaning devices
  646. * may be added to the queue. However, all devices will
  647. * be added to the tail of the queue, the queue won't
  648. * be re-organized, and the subtree of parent here should be locked
  649. * for purposes of adding/removing children.
  650. *
  651. * Note that we can not afford trying to walk the device list
  652. * once - our ``next'' device might be a child of the device
  653. * we are about to detach, so it would disappear.
  654. * Just play it safe and restart from the parent.
  655. */
  656. for (dev = TAILQ_LAST(&alldevs, devicelist);
  657. dev != NULL; dev = next_dev) {
  658. if (dev->dv_parent == parent) {
  659. if ((rv = config_detach(dev, flags)) != 0)
  660. return (rv);
  661. next_dev = TAILQ_LAST(&alldevs, devicelist);
  662. } else {
  663. next_dev = TAILQ_PREV(dev, devicelist, dv_list);
  664. }
  665. }
  666. return (0);
  667. }
  668. int
  669. config_suspend(struct device *dev, int act)
  670. {
  671. struct cfattach *ca = dev->dv_cfdata->cf_attach;
  672. int r;
  673. device_ref(dev);
  674. if (ca->ca_activate)
  675. r = (*ca->ca_activate)(dev, act);
  676. else
  677. r = config_activate_children(dev, act);
  678. device_unref(dev);
  679. return (r);
  680. }
  681. int
  682. config_suspend_all(int act)
  683. {
  684. struct device *mainbus = device_mainbus();
  685. struct device *mpath = device_mpath();
  686. int rv = 0;
  687. switch (act) {
  688. case DVACT_QUIESCE:
  689. case DVACT_SUSPEND:
  690. case DVACT_POWERDOWN:
  691. if (mpath) {
  692. rv = config_suspend(mpath, act);
  693. if (rv)
  694. return rv;
  695. }
  696. if (mainbus)
  697. rv = config_suspend(mainbus, act);
  698. break;
  699. case DVACT_RESUME:
  700. case DVACT_WAKEUP:
  701. if (mainbus) {
  702. rv = config_suspend(mainbus, act);
  703. if (rv)
  704. return rv;
  705. }
  706. if (mpath)
  707. rv = config_suspend(mpath, act);
  708. break;
  709. }
  710. return (rv);
  711. }
  712. /*
  713. * Call the ca_activate for each of our children, letting each
  714. * decide whether they wish to do the same for their children
  715. * and more.
  716. */
  717. int
  718. config_activate_children(struct device *parent, int act)
  719. {
  720. struct device *d;
  721. int rv = 0;
  722. for (d = TAILQ_NEXT(parent, dv_list); d != NULL;
  723. d = TAILQ_NEXT(d, dv_list)) {
  724. if (d->dv_parent != parent)
  725. continue;
  726. switch (act) {
  727. case DVACT_QUIESCE:
  728. case DVACT_SUSPEND:
  729. case DVACT_RESUME:
  730. case DVACT_WAKEUP:
  731. case DVACT_POWERDOWN:
  732. rv = config_suspend(d, act);
  733. break;
  734. case DVACT_DEACTIVATE:
  735. rv = config_deactivate(d);
  736. break;
  737. }
  738. if (rv == 0)
  739. continue;
  740. /*
  741. * Found a device that refuses the action.
  742. * If we were being asked to suspend, we can
  743. * try to resume all previous devices.
  744. */
  745. #ifdef DIAGNOSTIC
  746. printf("config_activate_children: device %s failed %d\n",
  747. d->dv_xname, act);
  748. #endif
  749. if (act == DVACT_RESUME)
  750. printf("failing resume cannot be handled\n");
  751. if (act == DVACT_POWERDOWN)
  752. return (rv);
  753. if (act != DVACT_SUSPEND)
  754. return (rv);
  755. d = TAILQ_PREV(d, devicelist, dv_list);
  756. for (; d != NULL && d != parent;
  757. d = TAILQ_PREV(d, devicelist, dv_list)) {
  758. if (d->dv_parent != parent)
  759. continue;
  760. printf("resume %s\n", d->dv_xname);
  761. config_suspend(d, DVACT_RESUME);
  762. }
  763. return (rv);
  764. }
  765. return (rv);
  766. }
  767. /*
  768. * Lookup a device in the cfdriver device array. Does not return a
  769. * device if it is not active.
  770. *
  771. * Increments ref count on the device by one, reflecting the
  772. * new reference created on the stack.
  773. *
  774. * Context: process only
  775. */
  776. struct device *
  777. device_lookup(struct cfdriver *cd, int unit)
  778. {
  779. struct device *dv = NULL;
  780. if (unit >= 0 && unit < cd->cd_ndevs)
  781. dv = (struct device *)(cd->cd_devs[unit]);
  782. if (!dv)
  783. return (NULL);
  784. if (!(dv->dv_flags & DVF_ACTIVE))
  785. dv = NULL;
  786. if (dv != NULL)
  787. device_ref(dv);
  788. return (dv);
  789. }
  790. struct device *
  791. device_mainbus(void)
  792. {
  793. extern struct cfdriver mainbus_cd;
  794. if (mainbus_cd.cd_ndevs < 1)
  795. return (NULL);
  796. return (mainbus_cd.cd_devs[0]);
  797. }
  798. struct device *
  799. device_mpath(void)
  800. {
  801. #if NMPATH > 0
  802. extern struct cfdriver mpath_cd;
  803. if (mpath_cd.cd_ndevs < 1)
  804. return (NULL);
  805. return (mpath_cd.cd_devs[0]);
  806. #else
  807. return (NULL);
  808. #endif
  809. }
  810. /*
  811. * Increments the ref count on the device structure. The device
  812. * structure is freed when the ref count hits 0.
  813. *
  814. * Context: process or interrupt
  815. */
  816. void
  817. device_ref(struct device *dv)
  818. {
  819. atomic_inc_int(&dv->dv_ref);
  820. }
  821. /*
  822. * Decrement the ref count on the device structure.
  823. *
  824. * free's the structure when the ref count hits zero.
  825. *
  826. * Context: process or interrupt
  827. */
  828. void
  829. device_unref(struct device *dv)
  830. {
  831. struct cfattach *ca;
  832. if (atomic_dec_int_nv(&dv->dv_ref) == 0) {
  833. ca = dv->dv_cfdata->cf_attach;
  834. free(dv, M_DEVBUF, ca->ca_devsize);
  835. }
  836. }