Index: subr_bus.c =================================================================== --- subr_bus.c (revision 196857) +++ subr_bus.c (working copy) @@ -125,10 +125,11 @@ #define DF_FIXEDCLASS 2 /* devclass specified at create time */ #define DF_WILDCARD 4 /* unit was originally wildcard */ #define DF_DESCMALLOCED 8 /* description was malloced */ -#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 */ +#define DF_QUIET 0x10 /* don't print verbose attach message */ +#define DF_DONENOMATCH 0x20 /* don't execute DEVICE_NOMATCH again */ +#define DF_EXTERNALSOFTC 0x40 /* softc not allocated by us */ +#define DF_REBID 0x80 /* Can rebid after attach */ +#define DF_TRANSITION 0x100 /* attach or detach running */ u_char order; /**< order from device_add_child_ordered() */ u_char pad; void *ivars; /**< instance variables */ @@ -2625,15 +2626,17 @@ { int error; - if (dev->state >= DS_ATTACHING) + GIANT_REQUIRED; + + if (dev->flags & DF_TRANSITION) return (0); device_sysctl_init(dev); if (!device_is_quiet(dev)) device_print_child(dev->parent, dev); - dev->state = DS_ATTACHING; + dev->flags |= DF_TRANSITION; if ((error = DEVICE_ATTACH(dev)) != 0) { - KASSERT(dev->state == DS_ATTACHING, - ("%s: %p device state must not been changing", __func__, + KASSERT(dev->flags & DF_TRANSITION, + ("%s: %p device must not drop DF_TRANSITION", __func__, dev)); printf("device_attach: %s%d attach returned %d\n", dev->driver->name, dev->unit, error); @@ -2643,12 +2646,15 @@ device_set_driver(dev, NULL); device_sysctl_fini(dev); dev->state = DS_NOTPRESENT; + dev->flags &= ~DF_TRANSITION; return (error); } - KASSERT(dev->state == DS_ATTACHING, - ("%s: %p device state must not been changing", __func__, dev)); + KASSERT(dev->flags & DF_TRANSITION, + ("%s: %p devie must not drop DF_TRANSITION", __func__, + dev)); device_sysctl_update(dev); dev->state = DS_ATTACHED; + dev->flags &= ~DF_TRANSITION; devadded(dev); return (0); } @@ -2681,17 +2687,20 @@ return (EBUSY); if (dev->state != DS_ATTACHED) return (0); - - dev->state = DS_DETACHING; + if (dev->flags & DF_TRANSITION) + return (0); + dev->flags |= DF_TRANSITION; if ((error = DEVICE_DETACH(dev)) != 0) { - KASSERT(dev->state == DS_DETACHING, - ("%s: %p device state must not been changing", __func__, + KASSERT(dev->flags & DF_TRANSITION, + ("%s: %p device must not drop DF_TRANSITION", __func__, dev)); dev->state = DS_ATTACHED; + dev->flags &= ~DF_TRANSITION; return (error); } - KASSERT(dev->state == DS_DETACHING, - ("%s: %p device state must not been changing", __func__, dev)); + KASSERT(dev->flags & DF_TRANSITION, + ("%s: %p device must not drop DF_TRANSITION", __func__, + dev)); devremoved(dev); if (!device_is_quiet(dev)) device_printf(dev, "detached\n"); @@ -2700,7 +2709,7 @@ if (!(dev->flags & DF_FIXEDCLASS)) devclass_delete_device(dev->devclass, dev); - + dev->flags &= ~DF_TRANSITION; dev->state = DS_NOTPRESENT; device_set_driver(dev, NULL); device_set_desc(dev, NULL); @@ -2746,7 +2755,7 @@ int device_shutdown(device_t dev) { - if (dev->state < DS_ATTACHED || dev->state == DS_DETACHING) + if (dev->state < DS_ATTACHED || (dev->flags & DF_TRANSITION)) return (0); return (DEVICE_SHUTDOWN(dev)); }