diff options
author | thompsa <thompsa@FreeBSD.org> | 2009-04-22 17:08:10 +0000 |
---|---|---|
committer | thompsa <thompsa@FreeBSD.org> | 2009-04-22 17:08:10 +0000 |
commit | 30310ed8e002b62a92673e2485607da8830bcb85 (patch) | |
tree | ad3cdcdae8a41de670d6abe848c78cdc9bd26fd1 | |
parent | c2a5eaf2ddb3fb9f79b11ad4d29a69313faff288 (diff) | |
download | FreeBSD-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.c | 8 | ||||
-rw-r--r-- | sys/dev/usb/usb_bus.h | 8 | ||||
-rw-r--r-- | sys/dev/usb/usb_transfer.c | 11 |
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 |