summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2009-04-22 17:08:10 +0000
committerthompsa <thompsa@FreeBSD.org>2009-04-22 17:08:10 +0000
commit30310ed8e002b62a92673e2485607da8830bcb85 (patch)
treead3cdcdae8a41de670d6abe848c78cdc9bd26fd1
parentc2a5eaf2ddb3fb9f79b11ad4d29a69313faff288 (diff)
downloadFreeBSD-src-30310ed8e002b62a92673e2485607da8830bcb85.zip
FreeBSD-src-30310ed8e002b62a92673e2485607da8830bcb85.tar.gz
MFp4 //depot/projects/usb@160706
Resolve possible device side mode deadlock by creating another thread. Submitted by: Hans Petter Selasky
-rw-r--r--sys/dev/usb/controller/usb_controller.c8
-rw-r--r--sys/dev/usb/usb_bus.h8
-rw-r--r--sys/dev/usb/usb_transfer.c11
3 files changed, 25 insertions, 2 deletions
diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
index 474cbe5..cf30051 100644
--- a/sys/dev/usb/controller/usb_controller.c
+++ b/sys/dev/usb/controller/usb_controller.c
@@ -169,6 +169,10 @@ usb2_detach(device_t dev)
usb2_proc_free(&bus->explore_proc);
+ /* Get rid of control transfer process */
+
+ usb2_proc_free(&bus->control_xfer_proc);
+
return (0);
}
@@ -412,6 +416,10 @@ usb2_attach_sub(device_t dev, struct usb2_bus *bus)
&bus->bus_mtx, pname, USB_PRI_MED)) {
printf("WARNING: Creation of USB explore "
"process failed.\n");
+ } else if (usb2_proc_create(&bus->control_xfer_proc,
+ &bus->bus_mtx, pname, USB_PRI_MED)) {
+ printf("WARNING: Creation of USB control transfer "
+ "process failed.\n");
} else {
/* Get final attach going */
USB_BUS_LOCK(bus);
diff --git a/sys/dev/usb/usb_bus.h b/sys/dev/usb/usb_bus.h
index 43cdf35..df3571f 100644
--- a/sys/dev/usb/usb_bus.h
+++ b/sys/dev/usb/usb_bus.h
@@ -62,7 +62,6 @@ struct usb2_sw_transfer {
struct usb2_bus {
struct usb2_bus_stat stats_err;
struct usb2_bus_stat stats_ok;
- struct usb2_process explore_proc;
struct usb2_sw_transfer roothub_req;
struct root_hold_token *bus_roothold;
/*
@@ -72,6 +71,13 @@ struct usb2_bus {
*/
struct usb2_process giant_callback_proc;
struct usb2_process non_giant_callback_proc;
+
+ /* Explore process */
+ struct usb2_process explore_proc;
+
+ /* Control request process */
+ struct usb2_process control_xfer_proc;
+
struct usb2_bus_msg explore_msg[2];
struct usb2_bus_msg detach_msg[2];
struct usb2_bus_msg attach_msg[2];
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index 41b07f1..bc44177 100644
--- a/sys/dev/usb/usb_transfer.c
+++ b/sys/dev/usb/usb_transfer.c
@@ -822,7 +822,16 @@ usb2_transfer_setup(struct usb2_device *udev,
info->done_m[1].hdr.pm_callback = &usb2_callback_proc;
info->done_m[1].xroot = info;
- if (xfer_mtx == &Giant)
+ /*
+ * In device side mode control endpoint
+ * requests need to run from a separate
+ * context, else there is a chance of
+ * deadlock!
+ */
+ if (setup_start == usb2_control_ep_cfg)
+ info->done_p =
+ &udev->bus->control_xfer_proc;
+ else if (xfer_mtx == &Giant)
info->done_p =
&udev->bus->giant_callback_proc;
else
OpenPOWER on IntegriCloud