aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2004-08-29 18:25:21 +0000
committerWarner Losh <imp@FreeBSD.org>2004-08-29 18:25:21 +0000
commitf52c5866ead1319d260be5c1a95cf8ef009bea0b (patch)
treed959deed0c9db592b83e366d8189808a94f9dfc7
parent3cdf2a3f2051e778fed51589bd0e500c3f2c8190 (diff)
Notes
-rw-r--r--sys/kern/subr_bus.c40
1 files changed, 36 insertions, 4 deletions
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index 9b1cafc18fe73..18f4362fd9336 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -124,6 +124,7 @@ struct device {
#define DF_QUIET 16 /* don't print verbose attach message */
#define DF_DONENOMATCH 32 /* don't execute DEVICE_NOMATCH again */
#define DF_EXTERNALSOFTC 64 /* softc not allocated by us */
+#define DF_REBID 128 /* Can rebid after attach */
u_char order; /**< order from device_add_child_ordered() */
u_char pad;
void *ivars; /**< instance variables */
@@ -1562,7 +1563,11 @@ device_probe_child(device_t dev, device_t child)
if (!dc)
panic("device_probe_child: parent device has no devclass");
- if (child->state == DS_ALIVE)
+ /*
+ * If the state is already probed, then return. However, don't
+ * return if we can rebid this object.
+ */
+ if (child->state == DS_ALIVE && (child->flags & DF_REBID) == 0)
return (0);
for (; dc; dc = dc->parent) {
@@ -1618,7 +1623,28 @@ device_probe_child(device_t dev, device_t child)
/*
* If we found a driver, change state and initialise the devclass.
*/
+ /* XXX What happens if we rebid and got no best? */
if (best) {
+ /*
+ * If this device was atached, and we were asked to
+ * rescan, and it is a different driver, then we have
+ * to detach the old driver and reattach this new one.
+ * Note, we don't have to check for DF_REBID here
+ * because if the state is > DS_ALIVE, we know it must
+ * be.
+ *
+ * This assumes that all DF_REBID drivers can have
+ * their probe routine called at any time and that
+ * they are idempotent as well as completely benign in
+ * normal operations.
+ *
+ * We also have to make sure that the detach
+ * succeeded, otherwise we fail the operation (or
+ * maybe it should just fail silently? I'm torn).
+ */
+ if (child->state > DS_ALIVE && best->driver != child->driver)
+ if ((result = device_detach(dev)) != 0)
+ return (result);
if (!child->devclass)
device_set_devclass(child, best->driver->name);
device_set_driver(child, best->driver);
@@ -1628,7 +1654,11 @@ device_probe_child(device_t dev, device_t child)
* sure that we have the right description.
*/
DEVICE_PROBE(child);
- }
+#if 0
+ child->flags |= DF_REBID;
+#endif
+ } else
+ child->flags &= ~DF_REBID;
child->state = DS_ALIVE;
bus_data_generation_update();
@@ -2140,7 +2170,7 @@ device_probe_and_attach(device_t dev)
{
int error;
- if (dev->state >= DS_ALIVE)
+ if (dev->state >= DS_ALIVE && (dev->flags & DF_REBID) == 0)
return (0);
if (!(dev->flags & DF_ENABLED)) {
@@ -2839,7 +2869,8 @@ bus_generic_driver_added(device_t dev, driver_t *driver)
DEVICE_IDENTIFY(driver, dev);
TAILQ_FOREACH(child, &dev->children, link) {
- if (child->state == DS_NOTPRESENT)
+ if (child->state == DS_NOTPRESENT ||
+ (child->flags & DF_REBID))
device_probe_and_attach(child);
}
}
@@ -3529,6 +3560,7 @@ print_device_short(device_t dev, int indent)
(dev->flags&DF_FIXEDCLASS? "fixed,":""),
(dev->flags&DF_WILDCARD? "wildcard,":""),
(dev->flags&DF_DESCMALLOCED? "descmalloced,":""),
+ (dev->flags&DF_REBID? "rebiddable,":""),
(dev->ivars? "":"no "),
(dev->softc? "":"no "),
dev->busy));