Allow device_busy() and device_unbusy() to be invoked while a device is
being attached. This is implemented by adding a new DS_ATTACHING state while a device's DEVICE_ATTACH() method is being invoked. A driver is required to not fail an attach of a busy device. The device's state will be promoted to DS_BUSY rather than DS_ACTIVE() if the device was marked busy during DEVICE_ATTACH(). Reviewed by: kib MFC after: 1 week
This commit is contained in:
parent
805bee55eb
commit
77b479e644
@ -2472,12 +2472,13 @@ device_disable(device_t dev)
|
||||
void
|
||||
device_busy(device_t dev)
|
||||
{
|
||||
if (dev->state < DS_ATTACHED)
|
||||
if (dev->state < DS_ATTACHING)
|
||||
panic("device_busy: called for unattached device");
|
||||
if (dev->busy == 0 && dev->parent)
|
||||
device_busy(dev->parent);
|
||||
dev->busy++;
|
||||
dev->state = DS_BUSY;
|
||||
if (dev->state == DS_ATTACHED)
|
||||
dev->state = DS_BUSY;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2486,14 +2487,16 @@ device_busy(device_t dev)
|
||||
void
|
||||
device_unbusy(device_t dev)
|
||||
{
|
||||
if (dev->state != DS_BUSY)
|
||||
if (dev->busy != 0 && dev->state != DS_BUSY &&
|
||||
dev->state != DS_ATTACHING)
|
||||
panic("device_unbusy: called for non-busy device %s",
|
||||
device_get_nameunit(dev));
|
||||
dev->busy--;
|
||||
if (dev->busy == 0) {
|
||||
if (dev->parent)
|
||||
device_unbusy(dev->parent);
|
||||
dev->state = DS_ATTACHED;
|
||||
if (dev->state == DS_BUSY)
|
||||
dev->state = DS_ATTACHED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2729,6 +2732,7 @@ device_attach(device_t dev)
|
||||
device_sysctl_init(dev);
|
||||
if (!device_is_quiet(dev))
|
||||
device_print_child(dev->parent, dev);
|
||||
dev->state = DS_ATTACHING;
|
||||
if ((error = DEVICE_ATTACH(dev)) != 0) {
|
||||
printf("device_attach: %s%d attach returned %d\n",
|
||||
dev->driver->name, dev->unit, error);
|
||||
@ -2736,11 +2740,15 @@ device_attach(device_t dev)
|
||||
devclass_delete_device(dev->devclass, dev);
|
||||
(void)device_set_driver(dev, NULL);
|
||||
device_sysctl_fini(dev);
|
||||
KASSERT(dev->busy == 0, ("attach failed but busy"));
|
||||
dev->state = DS_NOTPRESENT;
|
||||
return (error);
|
||||
}
|
||||
device_sysctl_update(dev);
|
||||
dev->state = DS_ATTACHED;
|
||||
if (dev->busy)
|
||||
dev->state = DS_BUSY;
|
||||
else
|
||||
dev->state = DS_ATTACHED;
|
||||
dev->flags &= ~DF_DONENOMATCH;
|
||||
devadded(dev);
|
||||
return (0);
|
||||
|
@ -52,6 +52,7 @@ struct u_businfo {
|
||||
typedef enum device_state {
|
||||
DS_NOTPRESENT = 10, /**< @brief not probed or probe failed */
|
||||
DS_ALIVE = 20, /**< @brief probe succeeded */
|
||||
DS_ATTACHING = 25, /**< @brief currently attaching */
|
||||
DS_ATTACHED = 30, /**< @brief attach method called */
|
||||
DS_BUSY = 40 /**< @brief device is open */
|
||||
} device_state_t;
|
||||
|
Loading…
Reference in New Issue
Block a user