aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAttilio Rao <attilio@FreeBSD.org>2009-08-02 14:28:40 +0000
committerAttilio Rao <attilio@FreeBSD.org>2009-08-02 14:28:40 +0000
commit444b91868b5294e3a2151fffa3b063763a562448 (patch)
treec00d808d1df8000c2086c86613be9ec8536a5e28 /sys
parentd40b91cb1354e9bae491567cc88c215eda16d649 (diff)
downloadsrc-444b91868b5294e3a2151fffa3b063763a562448.tar.gz
src-444b91868b5294e3a2151fffa3b063763a562448.zip
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/aac/aac.c8
-rw-r--r--sys/dev/acpica/acpi.c14
-rw-r--r--sys/dev/acpica/acpi_battery.c15
-rw-r--r--sys/dev/acpica/acpi_cpu.c2
-rw-r--r--sys/dev/acpica/acpi_dock.c8
-rw-r--r--sys/dev/acpica/acpi_thermal.c3
-rw-r--r--sys/dev/adb/adb_bus.c2
-rw-r--r--sys/dev/amdtemp/amdtemp.c2
-rw-r--r--sys/dev/amr/amr.c23
-rw-r--r--sys/dev/ata/ata-all.c34
-rw-r--r--sys/dev/atkbdc/psm.c4
-rw-r--r--sys/dev/bktr/bktr_os.c11
-rw-r--r--sys/dev/drm/drm_drv.c8
-rw-r--r--sys/dev/ips/ips_pci.c2
-rw-r--r--sys/dev/mfi/mfi.c20
-rw-r--r--sys/dev/mlx/mlx.c2
-rw-r--r--sys/dev/mmc/mmc.c2
-rw-r--r--sys/dev/pccbb/pccbb.c11
-rw-r--r--sys/dev/pst/pst-iop.c2
-rw-r--r--sys/dev/rp/rp.c4
-rw-r--r--sys/dev/sound/pci/hda/hdac.c2
-rw-r--r--sys/dev/twe/twe.c6
-rw-r--r--sys/dev/usb/controller/usb_controller.c30
-rw-r--r--sys/dev/usb/input/ukbd.c13
-rw-r--r--sys/dev/usb/net/usb_ethernet.c11
-rw-r--r--sys/dev/usb/usb_compat_linux.c27
-rw-r--r--sys/dev/usb/usb_dev.c6
-rw-r--r--sys/dev/usb/usb_handle_request.c12
-rw-r--r--sys/dev/usb/usb_hub.c19
-rw-r--r--sys/dev/usb/wlan/if_upgt.c4
-rw-r--r--sys/dev/xen/blkback/blkback.c4
-rw-r--r--sys/dev/xen/netback/netback.c4
-rw-r--r--sys/i386/acpica/acpi_machdep.c6
-rw-r--r--sys/i386/bios/smapi.c2
-rw-r--r--sys/i386/bios/smbios.c2
-rw-r--r--sys/i386/bios/vpd.c2
-rw-r--r--sys/kern/subr_bus.c89
-rw-r--r--sys/pc98/cbus/fdc.c6
-rw-r--r--sys/sys/bus.h8
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/xen/xenbus/xenbus_probe.c4
41 files changed, 304 insertions, 132 deletions
diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c
index f3d931aaf06b..c576a3584e5a 100644
--- a/sys/dev/aac/aac.c
+++ b/sys/dev/aac/aac.c
@@ -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);
}
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 63f95d3eb2c8..c3e4e521379a 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -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 @@ backout:
if (slp_state >= ACPI_SS_SLEPT)
acpi_enable_fixed_events(sc);
- mtx_unlock(&Giant);
+ newbus_xunlock();
#ifdef SMP
thread_lock(curthread);
diff --git a/sys/dev/acpica/acpi_battery.c b/sys/dev/acpica/acpi_battery.c
index dd2b3fa20808..1ec1413d2264 100644
--- a/sys/dev/acpica/acpi_battery.c
+++ b/sys/dev/acpica/acpi_battery.c
@@ -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);
diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c
index 5d8ad535998f..37134e23bf98 100644
--- a/sys/dev/acpica/acpi_cpu.c
+++ b/sys/dev/acpica/acpi_cpu.c
@@ -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
diff --git a/sys/dev/acpica/acpi_dock.c b/sys/dev/acpica/acpi_dock.c
index b7d2e3e444a4..95b9faec1576 100644
--- a/sys/dev/acpica/acpi_dock.c
+++ b/sys/dev/acpica/acpi_dock.c
@@ -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:
diff --git a/sys/dev/acpica/acpi_thermal.c b/sys/dev/acpica/acpi_thermal.c
index 962fdb7e9388..1e58d529fd0c 100644
--- a/sys/dev/acpica/acpi_thermal.c
+++ b/sys/dev/acpica/acpi_thermal.c
@@ -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++) {
diff --git a/sys/dev/adb/adb_bus.c b/sys/dev/adb/adb_bus.c
index faab048b52c9..c4a9c96ae9e8 100644
--- a/sys/dev/adb/adb_bus.c
+++ b/sys/dev/adb/adb_bus.c
@@ -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);
}
diff --git a/sys/dev/amdtemp/amdtemp.c b/sys/dev/amdtemp/amdtemp.c
index fdf087533c5f..ba7436aa57d2 100644
--- a/sys/dev/amdtemp/amdtemp.c
+++ b/sys/dev/amdtemp/amdtemp.c
@@ -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);
}
diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c
index 2061fcc801f9..688b2df63ad7 100644
--- a/sys/dev/amr/amr.c
+++ b/sys/dev/amr/amr.c
@@ -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);
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 1460a2117d4f..6696f0cff0c8 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -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;
}
diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c
index 93c9acb7a9c4..1fbdee76e25a 100644
--- a/sys/dev/atkbdc/psm.c
+++ b/sys/dev/atkbdc/psm.c
@@ -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);
}
diff --git a/sys/dev/bktr/bktr_os.c b/sys/dev/bktr/bktr_os.c
index 327c4bbdb959..1fd458cd3c10 100644
--- a/sys/dev/bktr/bktr_os.c
+++ b/sys/dev/bktr/bktr_os.c
@@ -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 );
}
diff --git a/sys/dev/drm/drm_drv.c b/sys/dev/drm/drm_drv.c
index 561afd5e8fb9..e12f8cdfa92d 100644
--- a/sys/dev/drm/drm_drv.c
+++ b/sys/dev/drm/drm_drv.c
@@ -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.
diff --git a/sys/dev/ips/ips_pci.c b/sys/dev/ips/ips_pci.c
index 9ccaf373b3e2..70e7d3be068c 100644
--- a/sys/dev/ips/ips_pci.c
+++ b/sys/dev/ips/ips_pci.c
@@ -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)
diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c
index eb18ffe4ce35..0ae585e892df 100644
--- a/sys/dev/mfi/mfi.c
+++ b/sys/dev/mfi/mfi.c
@@ -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 @@ out:
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 @@ out:
struct mfi_linux_ioc_aen l_aen;
int adapter;
+ newbus_slock();
devclass = devclass_find("mfi");
+ newbus_sunlock();
if (devclass == NULL)
return (ENOENT);
diff --git a/sys/dev/mlx/mlx.c b/sys/dev/mlx/mlx.c
index 6087216901fd..9e74f6245733 100644
--- a/sys/dev/mlx/mlx.c
+++ b/sys/dev/mlx/mlx.c
@@ -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);
/*
diff --git a/sys/dev/mmc/mmc.c b/sys/dev/mmc/mmc.c
index 68726675f81c..0fd424dbaf48 100644
--- a/sys/dev/mmc/mmc.c
+++ b/sys/dev/mmc/mmc.c
@@ -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);
}
diff --git a/sys/dev/pccbb/pccbb.c b/sys/dev/pccbb/pccbb.c
index a0585b00b8ea..f60118528ff8 100644
--- a/sys/dev/pccbb/pccbb.c
+++ b/sys/dev/pccbb/pccbb.c
@@ -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
diff --git a/sys/dev/pst/pst-iop.c b/sys/dev/pst/pst-iop.c
index d4e83f01ecbe..3fa37fdbfd31 100644
--- a/sys/dev/pst/pst-iop.c
+++ b/sys/dev/pst/pst-iop.c
@@ -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;
}
}
diff --git a/sys/dev/rp/rp.c b/sys/dev/rp/rp.c
index 520ca80f9301..45f59d37304b 100644
--- a/sys/dev/rp/rp.c
+++ b/sys/dev/rp/rp.c
@@ -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
diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c
index 9f4264d98ec0..bf99d54ea1f9 100644
--- a/sys/dev/sound/pci/hda/hdac.c
+++ b/sys/dev/sound/pci/hda/hdac.c
@@ -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();
}
/****************************************************************************
diff --git a/sys/dev/twe/twe.c b/sys/dev/twe/twe.c
index 59b5027adac9..2641fae5e852 100644
--- a/sys/dev/twe/twe.c
+++ b/sys/dev/twe/twe.c
@@ -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 */
diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
index 7a019dcaa7ac..f6776f01a4c5 100644
--- a/sys/dev/usb/controller/usb_controller.c
+++ b/sys/dev/usb/controller/usb_controller.c
@@ -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.
- */
- (udev->hub->explore) (udev);
-
- mtx_unlock(&Giant);
+ /* Explore the Root USB HUB. */
+ (udev->hub->explore) (udev);
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);
diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c
index 0d09ad43783a..2170b3700160 100644
--- a/sys/dev/usb/input/ukbd.c
+++ b/sys/dev/usb/input/ukbd.c
@@ -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);
}
diff --git a/sys/dev/usb/net/usb_ethernet.c b/sys/dev/usb/net/usb_ethernet.c
index 6cf446016e75..427137a92f26 100644
--- a/sys/dev/usb/net/usb_ethernet.c
+++ b/sys/dev/usb/net/usb_ethernet.c
@@ -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 */
diff --git a/sys/dev/usb/usb_compat_linux.c b/sys/dev/usb/usb_compat_linux.c
index 604ac4d88458..00fc86bdc988 100644
--- a/sys/dev/usb/usb_compat_linux.c
+++ b/sys/dev/usb/usb_compat_linux.c
@@ -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();
}
/*------------------------------------------------------------------------*
diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c
index cba8919255c8..b7c6553db75c 100644
--- a/sys/dev/usb/usb_dev.c
+++ b/sys/dev/usb/usb_dev.c
@@ -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);
}
diff --git a/sys/dev/usb/usb_handle_request.c b/sys/dev/usb/usb_handle_request.c
index a720919b7d80..2bc3eefd210e 100644
--- a/sys/dev/usb/usb_handle_request.c
+++ b/sys/dev/usb/usb_handle_request.c
@@ -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 @@ tr_repeat:
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);
}
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c
index 0defc97c30c9..a09be96b8e4b 100644
--- a/sys/dev/usb/usb_hub.c
+++ b/sys/dev/usb/usb_hub.c
@@ -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 @@ repeat:
/* 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 @@ repeat:
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 @@ repeat:
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 @@ repeat:
}
}
+ 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 */
diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c
index ff3220b716fd..8714645450e3 100644
--- a/sys/dev/usb/wlan/if_upgt.c
+++ b/sys/dev/usb/wlan/if_upgt.c
@@ -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);
diff --git a/sys/dev/xen/blkback/blkback.c b/sys/dev/xen/blkback/blkback.c
index 259f2f6c0418..535b1e078bc0 100644
--- a/sys/dev/xen/blkback/blkback.c
+++ b/sys/dev/xen/blkback/blkback.c
@@ -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;
}
diff --git a/sys/dev/xen/netback/netback.c b/sys/dev/xen/netback/netback.c
index a6111e265f58..cabc4ab72414 100644
--- a/sys/dev/xen/netback/netback.c
+++ b/sys/dev/xen/netback/netback.c
@@ -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;
}
diff --git a/sys/i386/acpica/acpi_machdep.c b/sys/i386/acpica/acpi_machdep.c
index e26cce9a7297..456867123b17 100644
--- a/sys/i386/acpica/acpi_machdep.c
+++ b/sys/i386/acpica/acpi_machdep.c
@@ -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;
diff --git a/sys/i386/bios/smapi.c b/sys/i386/bios/smapi.c
index e572664e2aca..74cf612182ae 100644
--- a/sys/i386/bios/smapi.c
+++ b/sys/i386/bios/smapi.c
@@ -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;
diff --git a/sys/i386/bios/smbios.c b/sys/i386/bios/smbios.c
index f38d98573993..37a3b2cd092f 100644
--- a/sys/i386/bios/smbios.c
+++ b/sys/i386/bios/smbios.c
@@ -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;
diff --git a/sys/i386/bios/vpd.c b/sys/i386/bios/vpd.c
index 246b76d35702..f816121260fe 100644
--- a/sys/i386/bios/vpd.c
+++ b/sys/i386/bios/vpd.c
@@ -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;
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index 2964b8c1a225..67f09182d5f1 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -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>
@@ -192,6 +193,54 @@ void print_devclass_list(void);
#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;
+ 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 @@ driver_module_handler(module_t mod, int what, void *arg)
error = EOPNOTSUPP;
break;
}
+ NBL_XUNLOCK();
return (error);
}
diff --git a/sys/pc98/cbus/fdc.c b/sys/pc98/cbus/fdc.c
index 8373f45163c5..294711787a9f 100644
--- a/sys/pc98/cbus/fdc.c
+++ b/sys/pc98/cbus/fdc.c
@@ -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;
diff --git a/sys/sys/bus.h b/sys/sys/bus.h
index 2362041dad26..7ed06f4fed91 100644
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -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.
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 1570900d1106..10a1a9a79f94 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -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>
diff --git a/sys/xen/xenbus/xenbus_probe.c b/sys/xen/xenbus/xenbus_probe.c
index f04f8eca4638..f930c8ff71b9 100644
--- a/sys/xen/xenbus/xenbus_probe.c
+++ b/sys/xen/xenbus/xenbus_probe.c
@@ -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);