Make the newbus subsystem Giant free by adding the new newbus sxlock.

The newbus lock is responsible for protecting newbus internIal structures,
device states and devclass flags. It is necessary to hold it when all
such datas are accessed. For the other operations, softc locking should
ensure enough protection to avoid races.

Newbus lock is automatically held when virtual operations on the device
and bus are invoked when loading the driver or when the suspend/resume
take place. For other 'spourious' operations trying to access/modify
the newbus topology, newbus lock needs to be automatically acquired and
dropped.

For the moment Giant is also acquired in some key point (modules subsystem)
in order to avoid problems before the 8.0 release as module handlers could
make assumptions about it. This Giant locking should go just after
the release happens.

Please keep in mind that the public interface can be expanded in order
to provide more support, if there are really necessities at some point
and also some bugs could arise as long as the patch needs a bit of
further testing.

Bump __FreeBSD_version in order to reflect the newbus lock introduction.

Reviewed by:    ed, hps, jhb, imp, mav, scottl
No answer by:   ariff, thompsa, yongari
Tested by:      pho,
                G. Trematerra <giovanni dot trematerra at gmail dot com>,
                Brandon Gooch <jamesbrandongooch at gmail dot com>
Sponsored by:   Yahoo! Incorporated
Approved by:	re (ksmith)
This commit is contained in:
Attilio Rao 2009-08-02 14:28:40 +00:00
parent d40b91cb13
commit 444b91868b
41 changed files with 305 additions and 133 deletions

View File

@ -3270,10 +3270,10 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
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 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
/* 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);
}

View File

@ -675,8 +675,6 @@ acpi_suspend(device_t dev)
device_t child, *devlist;
int error, i, numdevs, pstate;
GIANT_REQUIRED;
/* First give child devices a chance to suspend. */
error = bus_generic_suspend(dev);
if (error)
@ -719,8 +717,6 @@ acpi_resume(device_t dev)
int i, numdevs, error;
device_t child, *devlist;
GIANT_REQUIRED;
/*
* Put all devices in D0 before resuming them. Call _S0D on each one
* since some systems expect this.
@ -745,8 +741,6 @@ static int
acpi_shutdown(device_t dev)
{
GIANT_REQUIRED;
/* Allow children to shutdown first. */
bus_generic_shutdown(dev);
@ -2534,11 +2528,7 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
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 +2601,7 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
if (slp_state >= ACPI_SS_SLEPT)
acpi_enable_fixed_events(sc);
mtx_unlock(&Giant);
newbus_xunlock();
#ifdef SMP
thread_lock(curthread);

View File

@ -329,6 +329,7 @@ acpi_battery_find_dev(u_int logical_unit)
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 @@ acpi_battery_find_dev(u_int logical_unit)
found_unit++;
dev = NULL;
}
newbus_sunlock();
return (dev);
}
@ -369,13 +371,17 @@ acpi_battery_ioctl(u_long cmd, caddr_t addr, void *arg)
*/
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 @@ acpi_battery_sysctl(SYSCTL_HANDLER_ARGS)
{
int val, error;
/*
* Tolerate 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 @@ acpi_battery_units_sysctl(SYSCTL_HANDLER_ARGS)
{
int count, error;
/*
* Tolerate 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);

View File

@ -732,7 +732,9 @@ acpi_cpu_startup(void *arg)
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

View File

@ -188,12 +188,12 @@ acpi_dock_attach_later(void *context)
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 @@ acpi_dock_eject_child(ACPI_HANDLE handle, UINT32 level, void *context,
"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:

View File

@ -936,6 +936,8 @@ acpi_tz_thread(void *arg)
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 @@ acpi_tz_thread(void *arg)
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++) {

View File

@ -113,6 +113,7 @@ adb_bus_enumerate(void *xdev)
uint8_t i, next_free;
uint16_t r3;
newbus_xlock();
sc->sc_dev = dev;
sc->parent = device_get_parent(dev);
@ -187,6 +188,7 @@ adb_bus_enumerate(void *xdev)
}
bus_generic_attach(dev);
newbus_xunlock();
config_intrhook_disestablish(&sc->enum_hook);
}

View File

@ -269,6 +269,7 @@ amdtemp_intrhook(void *arg)
/*
* 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 @@ amdtemp_intrhook(void *arg)
"Max of sensor 0 / 1");
}
}
newbus_xunlock();
config_intrhook_disestablish(&sc->sc_ich);
}

View File

@ -90,6 +90,10 @@ __FBSDID("$FreeBSD$");
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 @@ amr_startup(void *arg)
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 @@ amr_startup(void *arg)
/* interrupts will be enabled before we do anything more */
sc->amr_state |= AMR_STATE_INTEN;
newbus_xunlock();
/*
* Start the timeout routine.
@ -434,7 +441,11 @@ static int
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);
@ -490,7 +501,11 @@ static int
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);
@ -507,6 +522,7 @@ amr_rescan_drives(struct cdev *dev)
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 @@ amr_rescan_drives(struct cdev *dev)
sc->amr_drive[i].al_disk = 0;
}
}
newbus_xunlock();
shutdown_out:
amr_startup(sc);
@ -805,7 +822,9 @@ amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, struct threa
struct amr_linux_ioctl ali;
int adapter, error;
newbus_slock();
devclass = devclass_find("amr");
newbus_sunlock();
if (devclass == NULL)
return (ENOENT);

View File

@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$");
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 @@ ata_conn_event(void *context, int dummy)
{
device_t dev = (device_t)context;
newbus_xlock();
ata_reinit(dev);
newbus_xunlock();
}
int
@ -246,7 +247,6 @@ ata_reinit(device_t dev)
/* 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 @@ ata_reinit(device_t dev)
}
}
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 @@ ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
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 @@ ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
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 @@ ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
if (ata_raid_ioctl_func)
error = ata_raid_ioctl_func(cmd, data);
}
newbus_xunlock();
return error;
}
@ -572,7 +581,7 @@ ata_boot_attach(void)
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 @@ ata_boot_attach(void)
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 @@ ata_identify(device_t dev)
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 @@ ata_identify(device_t dev)
/* 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 @@ ata_identify(device_t dev)
}
bus_generic_probe(dev);
bus_generic_attach(dev);
mtx_unlock(&Giant);
return 0;
}

View File

@ -1488,7 +1488,9 @@ psmopen(struct cdev *dev, int flag, int fmt, struct thread *td)
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 @@ psmclose(struct cdev *dev, int flag, int fmt, struct thread *td)
/* 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);
}

View File

@ -597,7 +597,9 @@ bktr_open( struct cdev *dev, int flags, int fmt, struct thread *td )
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 @@ bktr_open( struct cdev *dev, int flags, int fmt, struct thread *td )
}
/* 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 @@ bktr_close( struct cdev *dev, int flags, int fmt, struct thread *td )
/* 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 @@ bktr_close( struct cdev *dev, int flags, int fmt, struct thread *td )
break;
default:
return (ENXIO);
break;
}
newbus_xlock();
device_unbusy(devclass_get_device(bktr_devclass, unit));
newbus_xunlock();
return( result );
}

View File

@ -614,11 +614,13 @@ int drm_open(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
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 @@ void drm_close(void *data)
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 @@ void drm_close(void *data)
}
DRM_UNLOCK();
newbus_xunlock();
}
/* drm_ioctl is called whenever a process performs an ioctl on /dev/drm.

View File

@ -173,10 +173,12 @@ ips_intrhook(void *arg)
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)

View File

@ -1327,11 +1327,11 @@ mfi_add_ld_complete(struct mfi_command *cm)
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 @@ mfi_add_ld_complete(struct mfi_command *cm)
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 @@ mfi_check_command_post(struct mfi_softc *sc, struct mfi_command *cm)
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 @@ mfi_check_command_post(struct mfi_softc *sc, struct mfi_command *cm)
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 @@ mfi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td
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 @@ mfi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td
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 @@ mfi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td
struct mfi_linux_ioc_aen l_aen;
int adapter;
newbus_slock();
devclass = devclass_find("mfi");
newbus_sunlock();
if (devclass == NULL)
return (ENOENT);

View File

@ -772,7 +772,9 @@ mlx_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, struct threa
* Scan the controller to see whether new drives have appeared.
*/
case MLX_RESCAN_DRIVES:
newbus_xlock();
mlx_startup(sc);
newbus_xunlock();
return(0);
/*

View File

@ -1496,7 +1496,9 @@ mmc_delayed_attach(void *xsc)
{
struct mmc_softc *sc = xsc;
newbus_xlock();
mmc_scan(sc);
newbus_xunlock();
config_intrhook_disestablish(&sc->config_intrhook);
}

View File

@ -464,14 +464,7 @@ cbb_event_thread(void *arg)
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 @@ cbb_event_thread(void *arg)
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

View File

@ -152,7 +152,9 @@ iop_attach(void *arg)
break;
case I2O_CLASS_RANDOM_BLOCK_STORAGE:
newbus_xlock();
pst_add_raid(sc, &sc->lct[i]);
newbus_xunlock();
break;
}
}

View File

@ -903,7 +903,9 @@ rpopen(struct tty *tp)
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 @@ rpclose(struct tty *tp)
rp = tty_softc(tp);
rphardclose(tp);
newbus_xlock();
device_unbusy(rp->rp_ctlp->dev);
newbus_xunlock();
}
static void

View File

@ -7435,6 +7435,7 @@ hdac_attach2(void *arg)
quirks_on, quirks_off);
);
newbus_xlock();
hdac_lock(sc);
/* Remove ourselves from the config hooks */
@ -7674,6 +7675,7 @@ hdac_attach2(void *arg)
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();
}
/****************************************************************************

View File

@ -294,8 +294,10 @@ twe_init(struct twe_softc *sc)
/*
* 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 @@ twe_ioctl(struct twe_softc *sc, int ioctlcmd, void *addr)
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 */

View File

@ -143,9 +143,7 @@ usb_attach(device_t dev)
}
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,13 @@ usb_bus_explore(struct usb_proc_msg *pm)
}
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. */
(udev->hub->explore) (udev);
mtx_unlock(&Giant);
USB_BUS_LOCK(bus);
}
if (bus->bus_roothold != NULL) {
@ -269,7 +260,7 @@ usb_bus_detach(struct usb_proc_msg *pm)
device_set_softc(dev, NULL);
USB_BUS_UNLOCK(bus);
mtx_lock(&Giant);
newbus_xlock();
/* detach children first */
bus_generic_detach(dev);
@ -281,7 +272,7 @@ usb_bus_detach(struct usb_proc_msg *pm)
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 +341,7 @@ usb_bus_attach(struct usb_proc_msg *pm)
}
USB_BUS_UNLOCK(bus);
mtx_lock(&Giant); /* XXX not required by USB */
newbus_xlock();
/* default power_mask value */
bus->hw_power_state =
@ -383,7 +374,7 @@ usb_bus_attach(struct usb_proc_msg *pm)
err = USB_ERR_NOMEM;
}
mtx_unlock(&Giant);
newbus_xunlock();
USB_BUS_LOCK(bus);
if (err) {
@ -472,7 +463,7 @@ usb_post_init(void *arg)
int max;
int n;
mtx_lock(&Giant);
newbus_xlock();
usb_devclass_ptr = devclass_find("usbus");
@ -483,11 +474,8 @@ usb_post_init(void *arg)
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 +487,7 @@ usb_post_init(void *arg)
usb_needs_explore_all();
mtx_unlock(&Giant);
newbus_xunlock();
}
SYSINIT(usb_post_init, SI_SUB_KICK_SCHEDULER, SI_ORDER_ANY, usb_post_init, NULL);

View File

@ -745,7 +745,7 @@ ukbd_attach(device_t dev)
uint16_t n;
uint16_t hid_len;
mtx_assert(&Giant, MA_OWNED);
mtx_lock(&Giant);
kbd_init_struct(kbd, UKBD_DRIVER_NAME, KB_OTHER, unit, 0, 0, 0);
@ -854,9 +854,6 @@ ukbd_attach(device_t dev)
if (bootverbose) {
genkbd_diag(kbd, bootverbose);
}
/* lock keyboard mutex */
mtx_lock(&Giant);
/* start the keyboard */
@ -879,7 +876,7 @@ ukbd_detach(device_t dev)
struct ukbd_softc *sc = device_get_softc(dev);
int error;
mtx_assert(&Giant, MA_OWNED);
mtx_lock(&Giant);
DPRINTF("\n");
@ -916,6 +913,8 @@ ukbd_detach(device_t dev)
usb_callout_drain(&sc->sc_callout);
mtx_unlock(&Giant);
DPRINTF("%s: disconnected\n",
device_get_nameunit(dev));
@ -927,9 +926,9 @@ ukbd_resume(device_t dev)
{
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);
}

View File

@ -221,10 +221,10 @@ ue_attach_post_task(struct usb_proc_msg *_task)
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 @@ uether_ifdetach(struct usb_ether *ue)
/* 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 */

View File

@ -215,14 +215,12 @@ usb_linux_probe(device_t dev)
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 @@ usb_linux_get_usb_driver(struct usb_linux_softc *sc)
{
struct usb_driver *udrv;
mtx_lock(&Giant);
udrv = sc->sc_udrv;
mtx_unlock(&Giant);
return (udrv);
}
@ -260,13 +256,11 @@ usb_linux_attach(device_t dev)
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 @@ usb_linux_attach(device_t dev)
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 @@ usb_linux_detach(device_t dev)
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 @@ usb_unlink_bsd(struct usb_xfer *xfer,
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 @@ usb_linux_register(void *arg)
{
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 @@ usb_linux_deregister(void *arg)
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();
}
/*------------------------------------------------------------------------*

View File

@ -1040,9 +1040,14 @@ usb_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread*
* Performance optimisation: We try to check for IOCTL's that
* don't need the USB reference first. Then we grab the USB
* reference if we need it!
* Note that some ioctl_post handlers would need to run with the
* newbus lock held. It cannot be acquired later because it can
* introduce a LOR, so acquire it here.
*/
newbus_xlock();
err = usb_ref_device(cpd, &refs, 0 /* no uref */ );
if (err) {
newbus_xunlock();
return (ENXIO);
}
fflags = cpd->fflags;
@ -1076,6 +1081,7 @@ usb_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread*
}
done:
usb_unref_device(cpd, &refs);
newbus_xunlock();
return (err);
}

View File

@ -152,7 +152,7 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no)
* 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 @@ usb_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no)
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 @@ usb_handle_iface_request(struct usb_xfer *xfer,
* attach:
*/
USB_XFER_UNLOCK(xfer);
mtx_lock(&Giant); /* XXX */
newbus_xlock();
sx_xlock(udev->default_sx + 1);
error = ENXIO;
@ -353,20 +353,20 @@ usb_handle_iface_request(struct usb_xfer *xfer,
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);
}

View File

@ -234,8 +234,10 @@ uhub_explore_sub(struct uhub_softc *sc, struct usb_port *up)
if (child->driver_added_refcount != refcount) {
child->driver_added_refcount = refcount;
newbus_xlock();
err = usb_probe_and_attach(child,
USB_IFACE_INDEX_ANY);
newbus_xunlock();
if (err) {
goto done;
}
@ -318,9 +320,11 @@ uhub_reattach_port(struct uhub_softc *sc, uint8_t portno)
/* detach any existing devices */
if (child) {
newbus_xlock();
usb_free_device(child,
USB_UNCFG_FLAG_FREE_SUBDEV |
USB_UNCFG_FLAG_FREE_EP0);
newbus_xunlock();
child = NULL;
}
/* get fresh status */
@ -428,9 +432,10 @@ uhub_reattach_port(struct uhub_softc *sc, uint8_t portno)
mode = USB_MODE_HOST;
/* need to create a new child */
newbus_xlock();
child = usb_alloc_device(sc->sc_dev, udev->bus, udev,
udev->depth + 1, portno - 1, portno, speed, mode);
newbus_xunlock();
if (child == NULL) {
DPRINTFN(0, "could not allocate new device!\n");
goto error;
@ -439,9 +444,11 @@ uhub_reattach_port(struct uhub_softc *sc, uint8_t portno)
error:
if (child) {
newbus_xlock();
usb_free_device(child,
USB_UNCFG_FLAG_FREE_SUBDEV |
USB_UNCFG_FLAG_FREE_EP0);
newbus_xunlock();
child = NULL;
}
if (err == 0) {
@ -980,7 +987,6 @@ uhub_child_location_string(device_t parent, device_t child,
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 +998,6 @@ uhub_child_location_string(device_t parent, device_t child,
snprintf(buf, buflen, "port=%u interface=%u",
res.portno, res.iface_index);
done:
mtx_unlock(&Giant);
return (0);
}
@ -1006,7 +1011,6 @@ uhub_child_pnpinfo_string(device_t parent, device_t child,
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 +1041,6 @@ uhub_child_pnpinfo_string(device_t parent, device_t child,
goto done;
}
done:
mtx_unlock(&Giant);
return (0);
}
@ -1775,10 +1778,13 @@ usb_dev_resume_peer(struct usb_device *udev)
/* always update hardware power! */
(bus->methods->set_hw_power) (bus);
}
newbus_xlock();
sx_xlock(udev->default_sx + 1);
/* notify all sub-devices about resume */
err = usb_suspend_resume(udev, 0);
sx_unlock(udev->default_sx + 1);
newbus_xunlock();
/* check if peer has wakeup capability */
if (usb_peer_can_wakeup(udev)) {
@ -1844,10 +1850,13 @@ usb_dev_suspend_peer(struct usb_device *udev)
}
}
newbus_xlock();
sx_xlock(udev->default_sx + 1);
/* notify all sub-devices about suspend */
err = usb_suspend_resume(udev, 1);
sx_unlock(udev->default_sx + 1);
newbus_xunlock();
if (usb_peer_can_wakeup(udev)) {
/* allow device to do remote wakeup */

View File

@ -465,7 +465,7 @@ upgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
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 @@ upgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
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);

View File

@ -1156,7 +1156,7 @@ vbd_add_dev(struct xenbus_device *xdev)
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 @@ vbd_add_dev(struct xenbus_device *xdev)
done:
mtx_unlock(&Giant);
newbus_xunlock();
return err;
}

View File

@ -1388,7 +1388,7 @@ vif_add_dev(struct xenbus_device *xdev)
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 @@ vif_add_dev(struct xenbus_device *xdev)
done:
mtx_unlock(&Giant);
newbus_xunlock();
return err;
}

View File

@ -164,6 +164,7 @@ acpi_capm_get_info(apm_info_t aip)
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 @@ acpi_capm_get_info(apm_info_t aip)
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 @@ acpi_capm_get_pwstatus(apm_pwstatus_t app)
(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 @@ acpi_capm_get_pwstatus(apm_pwstatus_t app)
else
error = ENXIO;
}
newbus_sunlock();
if (error)
return (1);
@ -283,7 +287,9 @@ apmopen(struct cdev *dev, int flag, int fmt, struct thread *td)
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;

View File

@ -288,10 +288,12 @@ smapi_modevent (module_t mod, int what, void *arg)
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;

View File

@ -230,10 +230,12 @@ smbios_modevent (mod, what, arg)
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;

View File

@ -248,10 +248,12 @@ vpd_modevent (mod, what, arg)
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;

View File

@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <sys/selinfo.h>
#include <sys/signalvar.h>
#include <sys/sx.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/uio.h>
@ -191,6 +192,54 @@ void print_devclass_list(void);
#define print_devclass_list() /* nop */
#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 d_poll_t devpoll;
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 @@ devclass_delete_driver(devclass_t busclass, driver_t *driver)
int i;
int error;
NBL_ASSERT(SA_XLOCKED);
PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass)));
if (!dc)
@ -1759,6 +1808,7 @@ device_delete_child(device_t dev, device_t child)
int error;
device_t grandchild;
NBL_ASSERT(SA_XLOCKED);
PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev)));
/* remove children first */
@ -1857,7 +1907,7 @@ device_probe_child(device_t dev, device_t child)
int result, pri = 0;
int hasclass = (child->devclass != NULL);
GIANT_REQUIRED;
NBL_ASSERT(SA_XLOCKED);
dc = dev->devclass;
if (!dc)
@ -2508,7 +2558,7 @@ device_probe(device_t dev)
{
int error;
GIANT_REQUIRED;
NBL_ASSERT(SA_XLOCKED);
if (dev->state >= DS_ALIVE && (dev->flags & DF_REBID) == 0)
return (-1);
@ -2542,7 +2592,7 @@ device_probe_and_attach(device_t dev)
{
int error;
GIANT_REQUIRED;
NBL_ASSERT(SA_XLOCKED);
error = device_probe(dev);
if (error == -1)
@ -2576,6 +2626,8 @@ device_attach(device_t dev)
{
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 @@ device_detach(device_t dev)
{
int error;
GIANT_REQUIRED;
NBL_ASSERT(SA_XLOCKED);
PDEBUG(("%s", DEVICENAME(dev)));
if (dev->state == DS_BUSY)
@ -2661,6 +2713,8 @@ int
device_quiesce(device_t dev)
{
NBL_ASSERT(SA_XLOCKED);
PDEBUG(("%s", DEVICENAME(dev)));
if (dev->state == DS_BUSY)
return (EBUSY);
@ -2681,6 +2735,7 @@ device_quiesce(device_t dev)
int
device_shutdown(device_t dev)
{
if (dev->state < DS_ATTACHED)
return (0);
return (DEVICE_SHUTDOWN(dev));
@ -3096,6 +3151,8 @@ bus_generic_attach(device_t dev)
{
device_t child;
NBL_ASSERT(SA_XLOCKED);
TAILQ_FOREACH(child, &dev->children, link) {
device_probe_and_attach(child);
}
@ -3116,6 +3173,8 @@ bus_generic_detach(device_t dev)
device_t child;
int error;
NBL_ASSERT(SA_XLOCKED);
if (dev->state != DS_ATTACHED)
return (EBUSY);
@ -3996,6 +4055,7 @@ root_bus_module_handler(module_t mod, int what, void* arg)
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 @@ driver_module_handler(module_t mod, int what, void *arg)
kobj_class_t driver;
int error, pass;
dmd = (struct driver_module_data *)arg;
bus_devclass = devclass_find_internal(dmd->dmd_busname, NULL, TRUE);
error = 0;
dmd = (struct driver_module_data *)arg;
switch (what) {
/*
* 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);
if (bus_devclass == NULL) {
NBL_XUNLOCK();
return (ENOMEM);
}
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 @@ driver_module_handler(module_t mod, int what, void *arg)
error = EOPNOTSUPP;
break;
}
NBL_XUNLOCK();
return (error);
}

View File

@ -1499,7 +1499,9 @@ fdstrategy(struct bio *bp)
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 @@ fdstate(fdc_p fdc)
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 @@ retrier(struct fdc_data *fdc)
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;

View File

@ -478,6 +478,14 @@ int resource_set_string(const char *name, int unit, const char *resname,
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.

View File

@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
#define __FreeBSD_version 800106 /* Master, propagated to newvers */
#define __FreeBSD_version 800107 /* Master, propagated to newvers */
#ifndef LOCORE
#include <sys/types.h>

View File

@ -348,7 +348,9 @@ xenbus_devices_changed(struct xenbus_watch *watch,
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 @@ xenbus_attach_deferred(void *arg)
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);