Index: sys/kern/subr_bus.c =================================================================== --- sys/kern/subr_bus.c (revision 195974) +++ sys/kern/subr_bus.c (working copy) @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -192,6 +193,54 @@ #endif /* + * Newbus locking facilities. + */ +static struct sx newbus_lock; + +#define NBL_LOCK_INIT() sx_init(&newbus_lock, "newbus") +#define NBL_LOCK_DESTROY() sx_destroy(&newbus_lock) +#define NBL_XLOCK() sx_xlock(&newbus_lock) +#define NBL_SLOCK() sx_slock(&newbus_lock) +#define NBL_XUNLOCK() sx_xunlock(&newbus_lock) +#define NBL_SUNLOCK() sx_sunlock(&newbus_lock) +#ifdef INVARIANTS +#define NBL_ASSERT(what) do { \ + if (cold == 0) \ + sx_assert(&newbus_lock, (what)); \ +} while (0) +#else +#define NBL_ASSERT(what) +#endif + +void +newbus_xlock() +{ + + NBL_XLOCK(); +} + +void +newbus_slock() +{ + + NBL_SLOCK(); +} + +void +newbus_xunlock() +{ + + NBL_XUNLOCK(); +} + +void +newbus_sunlock() +{ + + NBL_SUNLOCK(); +} + +/* * dev sysctl tree */ @@ -364,7 +413,6 @@ static struct cdevsw dev_cdevsw = { .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, .d_open = devopen, .d_close = devclose, .d_read = devread, @@ -1061,6 +1109,7 @@ int i; int error; + NBL_ASSERT(SA_XLOCKED); PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass))); if (!dc) @@ -1759,6 +1808,7 @@ int error; device_t grandchild; + NBL_ASSERT(SA_XLOCKED); PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev))); /* remove children first */ @@ -1857,7 +1907,7 @@ int result, pri = 0; int hasclass = (child->devclass != NULL); - GIANT_REQUIRED; + NBL_ASSERT(SA_XLOCKED); dc = dev->devclass; if (!dc) @@ -2508,7 +2558,7 @@ { int error; - GIANT_REQUIRED; + NBL_ASSERT(SA_XLOCKED); if (dev->state >= DS_ALIVE && (dev->flags & DF_REBID) == 0) return (-1); @@ -2542,7 +2592,7 @@ { int error; - GIANT_REQUIRED; + NBL_ASSERT(SA_XLOCKED); error = device_probe(dev); if (error == -1) @@ -2576,6 +2626,8 @@ { int error; + NBL_ASSERT(SA_XLOCKED); + device_sysctl_init(dev); if (!device_is_quiet(dev)) device_print_child(dev->parent, dev); @@ -2617,7 +2669,7 @@ { int error; - GIANT_REQUIRED; + NBL_ASSERT(SA_XLOCKED); PDEBUG(("%s", DEVICENAME(dev))); if (dev->state == DS_BUSY) @@ -2661,6 +2713,8 @@ device_quiesce(device_t dev) { + NBL_ASSERT(SA_XLOCKED); + PDEBUG(("%s", DEVICENAME(dev))); if (dev->state == DS_BUSY) return (EBUSY); @@ -2681,6 +2735,7 @@ int device_shutdown(device_t dev) { + if (dev->state < DS_ATTACHED) return (0); return (DEVICE_SHUTDOWN(dev)); @@ -3096,6 +3151,8 @@ { device_t child; + NBL_ASSERT(SA_XLOCKED); + TAILQ_FOREACH(child, &dev->children, link) { device_probe_and_attach(child); } @@ -3116,6 +3173,8 @@ device_t child; int error; + NBL_ASSERT(SA_XLOCKED); + if (dev->state != DS_ATTACHED) return (EBUSY); @@ -3996,6 +4055,7 @@ switch (what) { case MOD_LOAD: TAILQ_INIT(&bus_data_devices); + NBL_LOCK_INIT(); kobj_class_compile((kobj_class_t) &root_driver); root_bus = make_device(NULL, "root", 0); root_bus->desc = "System root bus"; @@ -4055,14 +4115,28 @@ kobj_class_t driver; int error, pass; + error = 0; dmd = (struct driver_module_data *)arg; + + /* + * If MOD_SHUTDOWN is passed, return immediately in order to + * avoid unnecessary locking and a LOR with the modules sx lock. + */ + if (what == MOD_SHUTDOWN) + return (EOPNOTSUPP); + NBL_XLOCK(); bus_devclass = devclass_find_internal(dmd->dmd_busname, NULL, TRUE); - error = 0; + if (bus_devclass == NULL) { + NBL_XUNLOCK(); + return (ENOMEM); + } - switch (what) { + switch (what) { case MOD_LOAD: if (dmd->dmd_chainevh) error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg); + if (error != 0) + break; pass = dmd->dmd_pass; driver = dmd->dmd_driver; @@ -4115,6 +4189,7 @@ error = EOPNOTSUPP; break; } + NBL_XUNLOCK(); return (error); } Index: sys/dev/mlx/mlx.c =================================================================== --- sys/dev/mlx/mlx.c (revision 195974) +++ sys/dev/mlx/mlx.c (working copy) @@ -772,7 +772,9 @@ * Scan the controller to see whether new drives have appeared. */ case MLX_RESCAN_DRIVES: + newbus_xlock(); mlx_startup(sc); + newbus_xunlock(); return(0); /* Index: sys/dev/pccbb/pccbb.c =================================================================== --- sys/dev/pccbb/pccbb.c (revision 195974) +++ sys/dev/pccbb/pccbb.c (working copy) @@ -464,14 +464,7 @@ sc->flags |= CBB_KTHREAD_RUNNING; while ((sc->flags & CBB_KTHREAD_DONE) == 0) { mtx_unlock(&sc->mtx); - /* - * We take out Giant here because we need it deep, - * down in the bowels of the vm system for mapping the - * memory we need to read the CIS. In addition, since - * we are adding/deleting devices from the dev tree, - * and that code isn't MP safe, we have to hold Giant. - */ - mtx_lock(&Giant); + newbus_xlock(); status = cbb_get(sc, CBB_SOCKET_STATE); DPRINTF(("Status is 0x%x\n", status)); if (!CBB_CARD_PRESENT(status)) { @@ -497,7 +490,7 @@ not_a_card = 0; /* We know card type */ cbb_insert(sc); } - mtx_unlock(&Giant); + newbus_xunlock(); /* * First time through we need to tell mountroot that we're Index: sys/dev/mmc/mmc.c =================================================================== --- sys/dev/mmc/mmc.c (revision 195974) +++ sys/dev/mmc/mmc.c (working copy) @@ -1496,7 +1496,9 @@ { struct mmc_softc *sc = xsc; + newbus_xlock(); mmc_scan(sc); + newbus_xunlock(); config_intrhook_disestablish(&sc->config_intrhook); } Index: sys/dev/amr/amr.c =================================================================== --- sys/dev/amr/amr.c (revision 195974) +++ sys/dev/amr/amr.c (working copy) @@ -90,6 +90,10 @@ SYSCTL_NODE(_hw, OID_AUTO, amr, CTLFLAG_RD, 0, "AMR driver parameters"); +/* + * In order to get rid of Giant, amr_state should be protected by + * a proper softc lock for the cdev operations. + */ static d_open_t amr_open; static d_close_t amr_close; static d_ioctl_t amr_ioctl; @@ -312,9 +316,11 @@ config_intrhook_disestablish(&sc->amr_ich); sc->amr_ich.ich_func = NULL; + newbus_xlock(); /* get up-to-date drive information */ if (amr_query_controller(sc)) { device_printf(sc->amr_dev, "can't scan controller for drives\n"); + newbus_xunlock(); return; } @@ -347,6 +353,7 @@ /* interrupts will be enabled before we do anything more */ sc->amr_state |= AMR_STATE_INTEN; + newbus_xunlock(); /* * Start the timeout routine. @@ -434,8 +441,12 @@ amr_open(struct cdev *dev, int flags, int fmt, struct thread *td) { int unit = dev2unit(dev); - struct amr_softc *sc = devclass_get_softc(devclass_find("amr"), unit); + struct amr_softc *sc; + newbus_slock(); + sc = devclass_get_softc(devclass_find("amr"), unit); + newbus_sunlock(); + debug_called(1); sc->amr_state |= AMR_STATE_OPEN; @@ -490,8 +501,12 @@ amr_close(struct cdev *dev, int flags, int fmt, struct thread *td) { int unit = dev2unit(dev); - struct amr_softc *sc = devclass_get_softc(devclass_find("amr"), unit); + struct amr_softc *sc; + newbus_slock(); + sc = devclass_get_softc(devclass_find("amr"), unit); + newbus_sunlock(); + debug_called(1); sc->amr_state &= ~AMR_STATE_OPEN; @@ -507,6 +522,7 @@ struct amr_softc *sc = (struct amr_softc *)dev->si_drv1; int i, error = 0; + newbus_xlock(); sc->amr_state |= AMR_STATE_REMAP_LD; while (sc->amr_busyslots) { device_printf(sc->amr_dev, "idle controller\n"); @@ -530,6 +546,7 @@ sc->amr_drive[i].al_disk = 0; } } + newbus_xunlock(); shutdown_out: amr_startup(sc); @@ -805,7 +822,9 @@ struct amr_linux_ioctl ali; int adapter, error; + newbus_slock(); devclass = devclass_find("amr"); + newbus_sunlock(); if (devclass == NULL) return (ENOENT); Index: sys/dev/acpica/acpi.c =================================================================== --- sys/dev/acpica/acpi.c (revision 195974) +++ sys/dev/acpica/acpi.c (working copy) @@ -2534,11 +2534,7 @@ thread_unlock(curthread); #endif - /* - * Be sure to hold Giant across DEVICE_SUSPEND/RESUME since non-MPSAFE - * drivers need this. - */ - mtx_lock(&Giant); + newbus_xlock(); slp_state = ACPI_SS_NONE; @@ -2611,7 +2607,7 @@ if (slp_state >= ACPI_SS_SLEPT) acpi_enable_fixed_events(sc); - mtx_unlock(&Giant); + newbus_xunlock(); #ifdef SMP thread_lock(curthread); Index: sys/dev/acpica/acpi_dock.c =================================================================== --- sys/dev/acpica/acpi_dock.c (revision 195974) +++ sys/dev/acpica/acpi_dock.c (working copy) @@ -188,12 +188,12 @@ dev = (device_t)context; + newbus_xlock(); if (!device_is_enabled(dev)) device_enable(dev); - mtx_lock(&Giant); device_probe_and_attach(dev); - mtx_unlock(&Giant); + newbus_xunlock(); } static ACPI_STATUS @@ -299,11 +299,11 @@ "ejecting device for %s\n", acpi_name(handle)); dev = acpi_get_device(handle); + newbus_xlock(); if (dev != NULL && device_is_attached(dev)) { - mtx_lock(&Giant); device_detach(dev); - mtx_unlock(&Giant); } + newbus_xunlock(); acpi_SetInteger(handle, "_EJ0", 0); out: Index: sys/dev/acpica/acpi_cpu.c =================================================================== --- sys/dev/acpica/acpi_cpu.c (revision 195974) +++ sys/dev/acpica/acpi_cpu.c (working copy) @@ -732,7 +732,9 @@ int i; /* Get set of CPU devices */ + newbus_slock(); devclass_get_devices(acpi_cpu_devclass, &cpu_devices, &cpu_ndevices); + newbus_sunlock(); /* * Setup any quirks that might necessary now that we have probed Index: sys/dev/acpica/acpi_thermal.c =================================================================== --- sys/dev/acpica/acpi_thermal.c (revision 195974) +++ sys/dev/acpica/acpi_thermal.c (working copy) @@ -936,6 +936,8 @@ sc = NULL; for (;;) { + newbus_slock(); + /* If the number of devices has changed, re-evaluate. */ if (devclass_get_count(acpi_tz_devclass) != devcount) { if (devs != NULL) { @@ -948,6 +950,7 @@ for (i = 0; i < devcount; i++) sc[i] = device_get_softc(devs[i]); } + newbus_sunlock(); /* Check for temperature events and act on them. */ for (i = 0; i < devcount; i++) { Index: sys/dev/acpica/acpi_battery.c =================================================================== --- sys/dev/acpica/acpi_battery.c (revision 195974) +++ sys/dev/acpica/acpi_battery.c (working copy) @@ -88,7 +88,7 @@ batt_dc = devclass_find("battery"); if (batt_dc == NULL) return (0); - return (devclass_get_count(batt_dc)); + return(devclass_get_count(batt_dc)); } int @@ -329,6 +329,7 @@ dev = NULL; found_unit = 0; + newbus_slock(); batt_dc = devclass_find("battery"); maxunit = devclass_get_maxunit(batt_dc); for (i = 0; i < maxunit; i++) { @@ -340,6 +341,7 @@ found_unit++; dev = NULL; } + newbus_sunlock(); return (dev); } @@ -369,13 +371,17 @@ */ switch (cmd) { case ACPIIO_BATT_GET_UNITS: + newbus_slock(); *(int *)addr = acpi_battery_get_units(); + newbus_sunlock(); error = 0; break; case ACPIIO_BATT_GET_BATTINFO: if (dev != NULL || unit == ACPI_BATTERY_ALL_UNITS) { bzero(&ioctl_arg->battinfo, sizeof(ioctl_arg->battinfo)); + newbus_slock(); error = acpi_battery_get_battinfo(dev, &ioctl_arg->battinfo); + newbus_sunlock(); } break; case ACPIIO_BATT_GET_BIF: @@ -416,6 +422,11 @@ { int val, error; + /* + * Tollerate a race here because newbus lock can't be acquired before + * acpi_battery_get_battinfo() as it can create a LOR with the sysctl + * lock. + */ acpi_battery_get_battinfo(NULL, &acpi_battery_battinfo); val = *(u_int *)oidp->oid_arg1; error = sysctl_handle_int(oidp, &val, 0, req); @@ -427,6 +438,10 @@ { int count, error; + /* + * Tollerate a race here in order to avoid a LOR between sysctl lock + * and newbus lock. + */ count = acpi_battery_get_units(); error = sysctl_handle_int(oidp, &count, 0, req); return (error); Index: sys/dev/rp/rp.c =================================================================== --- sys/dev/rp/rp.c (revision 195974) +++ sys/dev/rp/rp.c (working copy) @@ -903,7 +903,9 @@ rp_callout_handle = timeout(rp_do_poll, (void *)NULL, POLL_INTERVAL); + newbus_xlock(); device_busy(rp->rp_ctlp->dev); + newbus_xunlock(); return(0); } @@ -914,7 +916,9 @@ rp = tty_softc(tp); rphardclose(tp); + newbus_xlock(); device_unbusy(rp->rp_ctlp->dev); + newbus_xunlock(); } static void Index: sys/dev/amdtemp/amdtemp.c =================================================================== --- sys/dev/amdtemp/amdtemp.c (revision 195974) +++ sys/dev/amdtemp/amdtemp.c (working copy) @@ -269,6 +269,7 @@ /* * dev.cpu.N.temperature. */ + newbus_xlock(); nexus = device_find_child(root_bus, "nexus", 0); acpi = device_find_child(nexus, "acpi", 0); @@ -285,6 +286,7 @@ "Max of sensor 0 / 1"); } } + newbus_xunlock(); config_intrhook_disestablish(&sc->sc_ich); } Index: sys/dev/atkbdc/psm.c =================================================================== --- sys/dev/atkbdc/psm.c (revision 195974) +++ sys/dev/atkbdc/psm.c (working copy) @@ -1488,7 +1488,9 @@ if (sc->state & PSM_OPEN) return (EBUSY); + newbus_xlock(); device_busy(devclass_get_device(psm_devclass, unit)); + newbus_xunlock(); /* Initialize state */ sc->mode.level = sc->dflt_mode.level; @@ -1643,7 +1645,9 @@ /* close is almost always successful */ sc->state &= ~PSM_OPEN; kbdc_lock(sc->kbdc, FALSE); + newbus_xlock(); device_unbusy(devclass_get_device(psm_devclass, unit)); + newbus_xunlock(); return (0); } Index: sys/dev/twe/twe.c =================================================================== --- sys/dev/twe/twe.c (revision 195974) +++ sys/dev/twe/twe.c (working copy) @@ -294,8 +294,10 @@ /* * Scan for drives */ + newbus_xlock(); for (i = 0; i < TWE_MAX_UNITS; i++) twe_add_unit(sc, i); + newbus_xunlock(); /* * Initialise connection with controller. @@ -621,11 +623,15 @@ break; case TWEIO_ADD_UNIT: + newbus_xlock(); error = twe_add_unit(sc, td->td_unit); + newbus_xunlock(); break; case TWEIO_DEL_UNIT: + newbus_xlock(); error = twe_del_unit(sc, td->td_unit); + newbus_xunlock(); break; /* XXX implement ATA PASSTHROUGH */ Index: sys/dev/mfi/mfi.c =================================================================== --- sys/dev/mfi/mfi.c (revision 195974) +++ sys/dev/mfi/mfi.c (working copy) @@ -1327,11 +1327,11 @@ mfi_release_command(cm); mtx_unlock(&sc->mfi_io_lock); - mtx_lock(&Giant); + newbus_xlock(); if ((child = device_add_child(sc->mfi_dev, "mfid", -1)) == NULL) { device_printf(sc->mfi_dev, "Failed to add logical disk\n"); free(ld_info, M_MFIBUF); - mtx_unlock(&Giant); + newbus_xunlock(); mtx_lock(&sc->mfi_io_lock); return; } @@ -1339,7 +1339,7 @@ device_set_ivars(child, ld_info); device_set_desc(child, "MFI Logical Disk"); bus_generic_attach(sc->mfi_dev); - mtx_unlock(&Giant); + newbus_xunlock(); mtx_lock(&sc->mfi_io_lock); } @@ -1805,9 +1805,9 @@ KASSERT(ld != NULL, ("volume dissappeared")); if (cm->cm_frame->header.cmd_status == MFI_STAT_OK) { mtx_unlock(&sc->mfi_io_lock); - mtx_lock(&Giant); + newbus_xlock(); device_delete_child(sc->mfi_dev, ld->ld_dev); - mtx_unlock(&Giant); + newbus_xunlock(); mtx_lock(&sc->mfi_io_lock); } else mfi_disk_enable(ld); @@ -1815,11 +1815,11 @@ case MFI_DCMD_CFG_CLEAR: if (cm->cm_frame->header.cmd_status == MFI_STAT_OK) { mtx_unlock(&sc->mfi_io_lock); - mtx_lock(&Giant); + newbus_xlock(); TAILQ_FOREACH_SAFE(ld, &sc->mfi_ld_tqh, ld_link, ldn) { device_delete_child(sc->mfi_dev, ld->ld_dev); } - mtx_unlock(&Giant); + newbus_xunlock(); mtx_lock(&sc->mfi_io_lock); } else { TAILQ_FOREACH(ld, &sc->mfi_ld_tqh, ld_link) @@ -1985,7 +1985,9 @@ adapter = ioc->mfi_adapter_no; if (device_get_unit(sc->mfi_dev) == 0 && adapter != 0) { + newbus_slock(); devclass = devclass_find("mfi"); + newbus_sunlock(); sc = devclass_get_softc(devclass, adapter); } mtx_lock(&sc->mfi_io_lock); @@ -2173,7 +2175,9 @@ struct mfi_linux_ioc_packet l_ioc; int adapter; + newbus_slock(); devclass = devclass_find("mfi"); + newbus_sunlock(); if (devclass == NULL) return (ENOENT); @@ -2194,7 +2198,9 @@ struct mfi_linux_ioc_aen l_aen; int adapter; + newbus_slock(); devclass = devclass_find("mfi"); + newbus_sunlock(); if (devclass == NULL) return (ENOENT); Index: sys/dev/sound/pci/hda/hdac.c =================================================================== --- sys/dev/sound/pci/hda/hdac.c (revision 195974) +++ sys/dev/sound/pci/hda/hdac.c (working copy) @@ -7435,6 +7435,7 @@ quirks_on, quirks_off); ); + newbus_xlock(); hdac_lock(sc); /* Remove ourselves from the config hooks */ @@ -7674,6 +7675,7 @@ SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)), OID_AUTO, "pindump", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev), sysctl_hdac_pindump, "I", "Dump pin states/data"); + newbus_xunlock(); } /**************************************************************************** Index: sys/dev/drm/drm_drv.c =================================================================== --- sys/dev/drm/drm_drv.c (revision 195974) +++ sys/dev/drm/drm_drv.c (working copy) @@ -614,11 +614,13 @@ if (!retcode) { atomic_inc(&dev->counts[_DRM_STAT_OPENS]); + newbus_xlock(); DRM_LOCK(); device_busy(dev->device); if (!dev->open_count++) retcode = drm_firstopen(dev); DRM_UNLOCK(); + newbus_xunlock(); } return retcode; @@ -632,6 +634,11 @@ DRM_DEBUG("open_count = %d\n", dev->open_count); + /* + * We require to lock newbus here for handling device_unbusy() and + * avoid a LOR with DRM_LOCK. + */ + newbus_xlock(); DRM_LOCK(); if (dev->driver->preclose != NULL) @@ -708,6 +715,7 @@ } DRM_UNLOCK(); + newbus_xunlock(); } /* drm_ioctl is called whenever a process performs an ioctl on /dev/drm. Index: sys/dev/aac/aac.c =================================================================== --- sys/dev/aac/aac.c (revision 195974) +++ sys/dev/aac/aac.c (working copy) @@ -3270,10 +3270,10 @@ while (co != NULL) { if (co->co_found == 0) { mtx_unlock(&sc->aac_io_lock); - mtx_lock(&Giant); + newbus_xlock(); device_delete_child(sc->aac_dev, co->co_disk); - mtx_unlock(&Giant); + newbus_xunlock(); mtx_lock(&sc->aac_io_lock); co_next = TAILQ_NEXT(co, co_link); mtx_lock(&sc->aac_container_lock); @@ -3291,9 +3291,9 @@ /* Attach the newly created containers */ if (added) { mtx_unlock(&sc->aac_io_lock); - mtx_lock(&Giant); + newbus_xlock(); bus_generic_attach(sc->aac_dev); - mtx_unlock(&Giant); + newbus_xunlock(); mtx_lock(&sc->aac_io_lock); } Index: sys/dev/ips/ips_pci.c =================================================================== --- sys/dev/ips/ips_pci.c (revision 195974) +++ sys/dev/ips/ips_pci.c (working copy) @@ -173,10 +173,12 @@ struct ips_softc *sc = (struct ips_softc *)arg; config_intrhook_disestablish(&sc->ips_ich); + newbus_xlock(); if (ips_adapter_init(sc)) ips_pci_free(sc); else sc->configured = 1; + newbus_xunlock(); } static int ips_pci_free(ips_softc_t *sc) Index: sys/dev/bktr/bktr_os.c =================================================================== --- sys/dev/bktr/bktr_os.c (revision 195974) +++ sys/dev/bktr/bktr_os.c (working copy) @@ -597,7 +597,9 @@ return( ENXIO ); /* Record that the device is now busy */ + newbus_xlock(); device_busy(devclass_get_device(bktr_devclass, unit)); + newbus_xunlock(); if (bt848_card != -1) { @@ -668,8 +670,11 @@ } /* If there was an error opening the device, undo the busy status */ - if (result != 0) + if (result != 0) { + newbus_xlock(); device_unbusy(devclass_get_device(bktr_devclass, unit)); + newbus_xunlock(); + } return( result ); } @@ -689,6 +694,7 @@ /* Get the device data */ bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); if (bktr == NULL) { + /* the device is no longer valid/functioning */ return (ENXIO); } @@ -705,10 +711,11 @@ break; default: return (ENXIO); - break; } + newbus_xlock(); device_unbusy(devclass_get_device(bktr_devclass, unit)); + newbus_xunlock(); return( result ); } Index: sys/dev/pst/pst-iop.c =================================================================== --- sys/dev/pst/pst-iop.c (revision 195974) +++ sys/dev/pst/pst-iop.c (working copy) @@ -152,7 +152,9 @@ break; case I2O_CLASS_RANDOM_BLOCK_STORAGE: + newbus_xlock(); pst_add_raid(sc, &sc->lct[i]); + newbus_xunlock(); break; } } Index: sys/dev/adb/adb_bus.c =================================================================== --- sys/dev/adb/adb_bus.c (revision 195974) +++ sys/dev/adb/adb_bus.c (working copy) @@ -113,6 +113,7 @@ uint8_t i, next_free; uint16_t r3; + newbus_xlock(); sc->sc_dev = dev; sc->parent = device_get_parent(dev); @@ -187,6 +188,7 @@ } bus_generic_attach(dev); + newbus_xunlock(); config_intrhook_disestablish(&sc->enum_hook); } Index: sys/dev/usb/controller/usb_controller.c =================================================================== --- sys/dev/usb/controller/usb_controller.c (revision 195974) +++ sys/dev/usb/controller/usb_controller.c (working copy) @@ -143,9 +143,7 @@ } if (usb_post_init_called) { - mtx_lock(&Giant); usb_attach_sub(dev, bus); - mtx_unlock(&Giant); usb_needs_explore(bus, 1); } return (0); /* return success */ @@ -228,20 +226,19 @@ } USB_BUS_UNLOCK(bus); - mtx_lock(&Giant); - /* * First update the USB power state! */ usb_bus_powerd(bus); + /* - * Explore the Root USB HUB. This call can sleep, - * exiting Giant, which is actually Giant. + * Explore the Root USB HUB. + * Acquire the newbus lock here because the function can + * recurse. */ + newbus_xlock(); (udev->hub->explore) (udev); - - mtx_unlock(&Giant); - + newbus_xunlock(); USB_BUS_LOCK(bus); } if (bus->bus_roothold != NULL) { @@ -269,7 +266,7 @@ device_set_softc(dev, NULL); USB_BUS_UNLOCK(bus); - mtx_lock(&Giant); + newbus_xlock(); /* detach children first */ bus_generic_detach(dev); @@ -281,7 +278,7 @@ usb_free_device(udev, USB_UNCFG_FLAG_FREE_EP0); - mtx_unlock(&Giant); + newbus_xunlock(); USB_BUS_LOCK(bus); /* clear bdev variable last */ bus->bdev = NULL; @@ -350,7 +347,7 @@ } USB_BUS_UNLOCK(bus); - mtx_lock(&Giant); /* XXX not required by USB */ + newbus_xlock(); /* default power_mask value */ bus->hw_power_state = @@ -383,7 +380,7 @@ err = USB_ERR_NOMEM; } - mtx_unlock(&Giant); + newbus_xunlock(); USB_BUS_LOCK(bus); if (err) { @@ -472,7 +469,7 @@ int max; int n; - mtx_lock(&Giant); + newbus_xlock(); usb_devclass_ptr = devclass_find("usbus"); @@ -483,11 +480,8 @@ dev = devclass_get_device(dc, n); if (dev && device_is_attached(dev)) { bus = device_get_ivars(dev); - if (bus) { - mtx_lock(&Giant); + if (bus) usb_attach_sub(dev, bus); - mtx_unlock(&Giant); - } } } } else { @@ -499,7 +493,7 @@ usb_needs_explore_all(); - mtx_unlock(&Giant); + newbus_xunlock(); } SYSINIT(usb_post_init, SI_SUB_KICK_SCHEDULER, SI_ORDER_ANY, usb_post_init, NULL); Index: sys/dev/usb/input/ukbd.c =================================================================== --- sys/dev/usb/input/ukbd.c (revision 195974) +++ sys/dev/usb/input/ukbd.c (working copy) @@ -745,8 +745,6 @@ uint16_t n; uint16_t hid_len; - mtx_assert(&Giant, MA_OWNED); - kbd_init_struct(kbd, UKBD_DRIVER_NAME, KB_OTHER, unit, 0, 0, 0); kbd->kb_data = (void *)sc; @@ -879,7 +877,7 @@ struct ukbd_softc *sc = device_get_softc(dev); int error; - mtx_assert(&Giant, MA_OWNED); + mtx_lock(&Giant); DPRINTF("\n"); @@ -916,6 +914,8 @@ usb_callout_drain(&sc->sc_callout); + mtx_unlock(&Giant); + DPRINTF("%s: disconnected\n", device_get_nameunit(dev)); @@ -927,9 +927,9 @@ { struct ukbd_softc *sc = device_get_softc(dev); - mtx_assert(&Giant, MA_OWNED); - + mtx_lock(&Giant); ukbd_clear_state(&sc->sc_kbd); + mtx_unlock(&Giant); return (0); } Index: sys/dev/usb/usb_hub.c =================================================================== --- sys/dev/usb/usb_hub.c (revision 195974) +++ sys/dev/usb/usb_hub.c (working copy) @@ -980,7 +980,6 @@ struct usb_hub *hub = sc->sc_udev->hub; struct hub_result res; - mtx_lock(&Giant); uhub_find_iface_index(hub, child, &res); if (!res.udev) { DPRINTF("device not on hub\n"); @@ -992,7 +991,6 @@ snprintf(buf, buflen, "port=%u interface=%u", res.portno, res.iface_index); done: - mtx_unlock(&Giant); return (0); } @@ -1006,7 +1004,6 @@ struct usb_interface *iface; struct hub_result res; - mtx_lock(&Giant); uhub_find_iface_index(hub, child, &res); if (!res.udev) { DPRINTF("device not on hub\n"); @@ -1037,7 +1034,6 @@ goto done; } done: - mtx_unlock(&Giant); return (0); } Index: sys/dev/usb/net/usb_ethernet.c =================================================================== --- sys/dev/usb/net/usb_ethernet.c (revision 195974) +++ sys/dev/usb/net/usb_ethernet.c (working copy) @@ -221,10 +221,10 @@ if (ue->ue_methods->ue_mii_upd != NULL && ue->ue_methods->ue_mii_sts != NULL) { - mtx_lock(&Giant); /* device_xxx() depends on this */ + newbus_xlock(); error = mii_phy_probe(ue->ue_dev, &ue->ue_miibus, ue_ifmedia_upd, ue->ue_methods->ue_mii_sts); - mtx_unlock(&Giant); + newbus_xunlock(); if (error) { device_printf(ue->ue_dev, "MII without any PHY\n"); goto error; @@ -279,9 +279,12 @@ /* detach miibus */ if (ue->ue_miibus != NULL) { - mtx_lock(&Giant); /* device_xxx() depends on this */ + + /* + * It is up to the callers to provide the correct + * newbus locking. + */ device_delete_child(ue->ue_dev, ue->ue_miibus); - mtx_unlock(&Giant); } /* detach ethernet */ Index: sys/dev/usb/usb_compat_linux.c =================================================================== --- sys/dev/usb/usb_compat_linux.c (revision 195974) +++ sys/dev/usb/usb_compat_linux.c (working copy) @@ -215,14 +215,12 @@ if (uaa->usb_mode != USB_MODE_HOST) { return (ENXIO); } - mtx_lock(&Giant); LIST_FOREACH(udrv, &usb_linux_driver_list, linux_driver_list) { if (usb_linux_lookup_id(udrv->id_table, uaa)) { err = 0; break; } } - mtx_unlock(&Giant); return (err); } @@ -239,9 +237,7 @@ { struct usb_driver *udrv; - mtx_lock(&Giant); udrv = sc->sc_udrv; - mtx_unlock(&Giant); return (udrv); } @@ -260,13 +256,11 @@ struct usb_driver *udrv; const struct usb_device_id *id = NULL; - mtx_lock(&Giant); LIST_FOREACH(udrv, &usb_linux_driver_list, linux_driver_list) { id = usb_linux_lookup_id(udrv->id_table, uaa); if (id) break; } - mtx_unlock(&Giant); if (id == NULL) { return (ENXIO); @@ -287,9 +281,7 @@ return (ENXIO); } } - mtx_lock(&Giant); LIST_INSERT_HEAD(&usb_linux_attached_list, sc, sc_attached_list); - mtx_unlock(&Giant); /* success */ return (0); @@ -307,14 +299,12 @@ struct usb_linux_softc *sc = device_get_softc(dev); struct usb_driver *udrv = NULL; - mtx_lock(&Giant); if (sc->sc_attached_list.le_prev) { LIST_REMOVE(sc, sc_attached_list); sc->sc_attached_list.le_prev = NULL; udrv = sc->sc_udrv; sc->sc_udrv = NULL; } - mtx_unlock(&Giant); if (udrv && udrv->disconnect) { (udrv->disconnect) (sc->sc_ui); @@ -474,13 +464,10 @@ if (!usbd_transfer_pending(xfer)) return; if (xfer->priv_fifo == (void *)urb) { - if (drain) { - mtx_unlock(&Giant); + if (drain) usbd_transfer_drain(xfer); - mtx_lock(&Giant); - } else { + else usbd_transfer_stop(xfer); - } usbd_transfer_start(xfer); } } @@ -1148,9 +1135,9 @@ { struct usb_driver *drv = arg; - mtx_lock(&Giant); + newbus_xlock(); LIST_INSERT_HEAD(&usb_linux_driver_list, drv, linux_driver_list); - mtx_unlock(&Giant); + newbus_xunlock(); usb_needs_explore_all(); } @@ -1172,16 +1159,16 @@ struct usb_linux_softc *sc; repeat: - mtx_lock(&Giant); + newbus_xlock(); LIST_FOREACH(sc, &usb_linux_attached_list, sc_attached_list) { if (sc->sc_udrv == drv) { - mtx_unlock(&Giant); device_detach(sc->sc_fbsd_dev); + newbus_xunlock(); goto repeat; } } LIST_REMOVE(drv, linux_driver_list); - mtx_unlock(&Giant); + newbus_xunlock(); } /*------------------------------------------------------------------------* Index: sys/dev/usb/usb_handle_request.c =================================================================== --- sys/dev/usb/usb_handle_request.c (revision 195974) +++ sys/dev/usb/usb_handle_request.c (working copy) @@ -152,7 +152,7 @@ * attach: */ USB_XFER_UNLOCK(xfer); - mtx_lock(&Giant); /* XXX */ + newbus_xlock(); sx_xlock(udev->default_sx + 1); if (conf_no == USB_UNCONFIG_NO) { @@ -176,8 +176,8 @@ goto done; } done: - mtx_unlock(&Giant); /* XXX */ sx_unlock(udev->default_sx + 1); + newbus_xunlock(); USB_XFER_LOCK(xfer); return (err); } @@ -236,7 +236,7 @@ * attach: */ USB_XFER_UNLOCK(xfer); - mtx_lock(&Giant); /* XXX */ + newbus_xlock(); sx_xlock(udev->default_sx + 1); error = ENXIO; @@ -353,20 +353,20 @@ goto tr_stalled; } tr_valid: - mtx_unlock(&Giant); sx_unlock(udev->default_sx + 1); + newbus_xunlock(); USB_XFER_LOCK(xfer); return (0); tr_short: - mtx_unlock(&Giant); sx_unlock(udev->default_sx + 1); + newbus_xunlock(); USB_XFER_LOCK(xfer); return (USB_ERR_SHORT_XFER); tr_stalled: - mtx_unlock(&Giant); sx_unlock(udev->default_sx + 1); + newbus_xunlock(); USB_XFER_LOCK(xfer); return (USB_ERR_STALLED); } Index: sys/dev/usb/wlan/if_upgt.c =================================================================== --- sys/dev/usb/wlan/if_upgt.c (revision 195974) +++ sys/dev/usb/wlan/if_upgt.c (working copy) @@ -465,7 +465,7 @@ switch (cmd) { case SIOCSIFFLAGS: - mtx_lock(&Giant); + newbus_xlock(); if (ifp->if_flags & IFF_UP) { if (ifp->if_drv_flags & IFF_DRV_RUNNING) { if ((ifp->if_flags ^ sc->sc_if_flags) & @@ -482,7 +482,7 @@ sc->sc_if_flags = ifp->if_flags; if (startall) ieee80211_start_all(ic); - mtx_unlock(&Giant); + newbus_xunlock(); break; case SIOCGIFMEDIA: error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); Index: sys/dev/xen/netback/netback.c =================================================================== --- sys/dev/xen/netback/netback.c (revision 195974) +++ sys/dev/xen/netback/netback.c (working copy) @@ -1388,7 +1388,7 @@ devclass_t dc; int err = 0; - mtx_lock(&Giant); + newbus_xlock(); /* We will add a vif device as a child of nexus0 (for now) */ if (!(dc = devclass_find("nexus")) || @@ -1415,7 +1415,7 @@ done: - mtx_unlock(&Giant); + newbus_xunlock(); return err; } Index: sys/dev/xen/blkback/blkback.c =================================================================== --- sys/dev/xen/blkback/blkback.c (revision 195974) +++ sys/dev/xen/blkback/blkback.c (working copy) @@ -1156,7 +1156,7 @@ devclass_t dc; int err = 0; - mtx_lock(&Giant); + newbus_xlock(); /* We will add a vbd device as a child of nexus0 (for now) */ if (!(dc = devclass_find("nexus")) || @@ -1183,7 +1183,7 @@ done: - mtx_unlock(&Giant); + newbus_xunlock(); return err; } Index: sys/dev/ata/ata-all.c =================================================================== --- sys/dev/ata/ata-all.c (revision 195974) +++ sys/dev/ata/ata-all.c (working copy) @@ -54,7 +54,6 @@ static d_ioctl_t ata_ioctl; static struct cdevsw ata_cdevsw = { .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, /* we need this as newbus isn't mpsafe */ .d_ioctl = ata_ioctl, .d_name = "ata", }; @@ -204,7 +203,9 @@ { device_t dev = (device_t)context; + newbus_xlock(); ata_reinit(dev); + newbus_xunlock(); } int @@ -246,7 +247,6 @@ /* reinit the children and delete any that fails */ if (!device_get_children(dev, &children, &nchildren)) { - mtx_lock(&Giant); /* newbus suckage it needs Giant */ for (i = 0; i < nchildren; i++) { /* did any children go missing ? */ if (children[i] && device_is_attached(children[i]) && @@ -269,7 +269,6 @@ } } free(children, M_TEMP); - mtx_unlock(&Giant); /* newbus suckage dealt with, release Giant */ } /* if we still have a good request put it on the queue again */ @@ -395,6 +394,7 @@ int *value = (int *)data; int i, nchildren, error = ENOTTY; + newbus_xlock(); switch (cmd) { case IOCATAGMAXCHANNEL: /* In case we have channel 0..n this will return n+1. */ @@ -405,32 +405,40 @@ case IOCATAREINIT: if (*value >= devclass_get_maxunit(ata_devclass) || !(device = devclass_get_device(ata_devclass, *value)) || - !device_is_attached(device)) + !device_is_attached(device)) { + newbus_xunlock(); return ENXIO; + } error = ata_reinit(device); break; case IOCATAATTACH: if (*value >= devclass_get_maxunit(ata_devclass) || !(device = devclass_get_device(ata_devclass, *value)) || - !device_is_attached(device)) + !device_is_attached(device)) { + newbus_xunlock(); return ENXIO; + } error = DEVICE_ATTACH(device); break; case IOCATADETACH: if (*value >= devclass_get_maxunit(ata_devclass) || !(device = devclass_get_device(ata_devclass, *value)) || - !device_is_attached(device)) + !device_is_attached(device)) { + newbus_xunlock(); return ENXIO; + } error = DEVICE_DETACH(device); break; case IOCATADEVICES: if (devices->channel >= devclass_get_maxunit(ata_devclass) || !(device = devclass_get_device(ata_devclass, devices->channel)) || - !device_is_attached(device)) + !device_is_attached(device)) { + newbus_xunlock(); return ENXIO; + } bzero(devices->name[0], 32); bzero(&devices->params[0], sizeof(struct ata_params)); bzero(devices->name[1], 32); @@ -465,6 +473,7 @@ if (ata_raid_ioctl_func) error = ata_raid_ioctl_func(cmd, data); } + newbus_xunlock(); return error; } @@ -572,7 +581,7 @@ struct ata_channel *ch; int ctlr; - mtx_lock(&Giant); /* newbus suckage it needs Giant */ + newbus_xlock(); /* kick of probe and attach on all channels */ for (ctlr = 0; ctlr < devclass_get_maxunit(ata_devclass); ctlr++) { @@ -587,8 +596,7 @@ free(ata_delayed_attach, M_TEMP); ata_delayed_attach = NULL; } - - mtx_unlock(&Giant); /* newbus suckage dealt with, release Giant */ + newbus_xunlock(); } @@ -717,7 +725,6 @@ if (bootverbose) device_printf(dev, "Identifying devices: %08x\n", ch->devices); - mtx_lock(&Giant); /* Skip existing devices. */ if (!device_get_children(dev, &children, &nchildren)) { for (i = 0; i < nchildren; i++) { @@ -729,10 +736,8 @@ /* Create new devices. */ if (bootverbose) device_printf(dev, "New devices: %08x\n", n); - if (n == 0) { - mtx_unlock(&Giant); + if (n == 0) return (0); - } for (i = 0; i < ATA_PM; ++i) { if (n & (((ATA_ATA_MASTER | ATA_ATAPI_MASTER) << i))) { int unit = -1; @@ -775,7 +780,6 @@ } bus_generic_probe(dev); bus_generic_attach(dev); - mtx_unlock(&Giant); return 0; } Index: sys/pc98/cbus/fdc.c =================================================================== --- sys/pc98/cbus/fdc.c (revision 195974) +++ sys/pc98/cbus/fdc.c (working copy) @@ -1499,7 +1499,9 @@ bioq_disksort(&fdc->head, bp); untimeout(fd_turnoff, fd, fd->toffhandle); /* a good idea */ devstat_start_transaction_bio(fd->device_stats, bp); + newbus_xlock(); device_busy(fd->dev); + newbus_xunlock(); fdstart(fdc); splx(s); return; @@ -2178,7 +2180,9 @@ fd->skip = 0; bp->bio_resid = 0; fdc->bp = NULL; + newbus_xlock(); device_unbusy(fd->dev); + newbus_xunlock(); biofinish(bp, fd->device_stats, 0); fdc->fd = (fd_p) 0; fdc->fdu = -1; @@ -2339,7 +2343,9 @@ bp->bio_resid = 0; fdc->bp = NULL; fdc->fd->skip = 0; + newbus_xlock(); device_unbusy(fd->dev); + newbus_xunlock(); biofinish(bp, fdc->fd->device_stats, 0); fdc->state = FINDWORK; fdc->flags |= FDC_NEEDS_RESET; Index: sys/i386/acpica/acpi_machdep.c =================================================================== --- sys/i386/acpica/acpi_machdep.c (revision 195974) +++ sys/i386/acpica/acpi_machdep.c (working copy) @@ -164,6 +164,7 @@ else aip->ai_acline = acline; /* on/off */ + newbus_slock(); if (acpi_battery_get_battinfo(NULL, &batt) != 0) { aip->ai_batt_stat = APM_UNKNOWN; aip->ai_batt_life = APM_UNKNOWN; @@ -175,6 +176,7 @@ aip->ai_batt_time = (batt.min == -1) ? -1 : batt.min * 60; aip->ai_batteries = acpi_battery_get_units(); } + newbus_sunlock(); return (0); } @@ -190,6 +192,7 @@ (app->ap_device < PMDV_BATT0 || app->ap_device > PMDV_BATT_ALL)) return (1); + newbus_slock(); if (app->ap_device == PMDV_ALLDEV) error = acpi_battery_get_battinfo(NULL, &batt); else { @@ -200,6 +203,7 @@ else error = ENXIO; } + newbus_sunlock(); if (error) return (1); @@ -283,7 +287,9 @@ struct acpi_softc *acpi_sc; struct apm_clone_data *clone; + newbus_slock(); acpi_sc = devclass_get_softc(devclass_find("acpi"), 0); + newbus_sunlock(); clone = apm_create_clone(dev, acpi_sc); dev->si_drv1 = clone; Index: sys/i386/bios/smapi.c =================================================================== --- sys/i386/bios/smapi.c (revision 195974) +++ sys/i386/bios/smapi.c (working copy) @@ -288,10 +288,12 @@ case MOD_LOAD: break; case MOD_UNLOAD: + newbus_xlock(); devclass_get_devices(smapi_devclass, &devs, &count); for (i = 0; i < count; i++) { device_delete_child(device_get_parent(devs[i]), devs[i]); } + newbus_xunlock(); break; default: break; Index: sys/i386/bios/vpd.c =================================================================== --- sys/i386/bios/vpd.c (revision 195974) +++ sys/i386/bios/vpd.c (working copy) @@ -248,10 +248,12 @@ case MOD_LOAD: break; case MOD_UNLOAD: + newbus_xlock(); devclass_get_devices(vpd_devclass, &devs, &count); for (i = 0; i < count; i++) { device_delete_child(device_get_parent(devs[i]), devs[i]); } + newbus_xunlock(); break; default: break; Index: sys/i386/bios/smbios.c =================================================================== --- sys/i386/bios/smbios.c (revision 195974) +++ sys/i386/bios/smbios.c (working copy) @@ -230,10 +230,12 @@ case MOD_LOAD: break; case MOD_UNLOAD: + newbus_xlock(); devclass_get_devices(smbios_devclass, &devs, &count); for (i = 0; i < count; i++) { device_delete_child(device_get_parent(devs[i]), devs[i]); } + newbus_xunlock(); break; default: break; Index: sys/xen/xenbus/xenbus_probe.c =================================================================== --- sys/xen/xenbus/xenbus_probe.c (revision 195974) +++ sys/xen/xenbus/xenbus_probe.c (working copy) @@ -348,7 +348,9 @@ if (p) *p = 0; + newbus_xlock(); xenbus_add_device(dev, bus, type, id); + newbus_xunlock(); taskqueue_enqueue(taskqueue_thread, &sc->xs_probechildren); out: free(node, M_DEVBUF); @@ -361,7 +363,9 @@ struct xenbus_softc *sc = device_get_softc(dev); int error; + newbus_xlock(); error = xenbus_enumerate_bus(dev, "device"); + newbus_xunlock(); if (error) return; xenbus_probe_children(dev); Index: sys/sys/bus.h =================================================================== --- sys/sys/bus.h (revision 195974) +++ sys/sys/bus.h (working copy) @@ -478,6 +478,14 @@ int bus_data_generation_check(int generation); void bus_data_generation_update(void); +/* + * Exported locking facilities. + */ +void newbus_xlock(void); +void newbus_slock(void); +void newbus_xunlock(void); +void newbus_sunlock(void); + /** * Some convenience defines for probe routines to return. These are just * suggested values, and there's nothing magical about them.