summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb')
-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
8 files changed, 57 insertions, 65 deletions
diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
index 7a019dc..f6776f01 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 0d09ad4..2170b37 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 6cf4460..427137a 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 604ac4d..00fc86b 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 cba8919..b7c6553 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 a720919..2bc3eef 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 0defc97..a09be96 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 ff3220b..8714645 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);
OpenPOWER on IntegriCloud