summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2012-03-03 08:11:04 +0000
committerhselasky <hselasky@FreeBSD.org>2012-03-03 08:11:04 +0000
commit402a0f9de41a1a087445529e59d3183a11d266b9 (patch)
treeb75a2ff6fb6b2e6ad6d704f7ea678393b2a2c432
parentd236ad156cee598edf03efc334a1db371af5a4e9 (diff)
downloadFreeBSD-src-402a0f9de41a1a087445529e59d3183a11d266b9.zip
FreeBSD-src-402a0f9de41a1a087445529e59d3183a11d266b9.tar.gz
Make sure that the USB system suspend event is executed synchronously
and not asynchronously. This fixes problems related to USB system suspend and resume. It is assumed that we are always allowed to sleep from the device_suspend() method. MFC after: 1 week Submitted by: jkim
-rw-r--r--sys/dev/usb/controller/usb_controller.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
index 0f942e1..f678427 100644
--- a/sys/dev/usb/controller/usb_controller.c
+++ b/sys/dev/usb/controller/usb_controller.c
@@ -89,10 +89,15 @@ TUNABLE_INT("hw.usb.no_boot_wait", &usb_no_boot_wait);
SYSCTL_INT(_hw_usb, OID_AUTO, no_boot_wait, CTLFLAG_RDTUN, &usb_no_boot_wait, 0,
"No USB device enumerate waiting at boot.");
+static int usb_no_suspend_wait = 0;
+TUNABLE_INT("hw.usb.no_suspend_wait", &usb_no_suspend_wait);
+SYSCTL_INT(_hw_usb, OID_AUTO, no_suspend_wait, CTLFLAG_RW|CTLFLAG_TUN,
+ &usb_no_suspend_wait, 0, "No USB device waiting at system suspend.");
+
static int usb_no_shutdown_wait = 0;
TUNABLE_INT("hw.usb.no_shutdown_wait", &usb_no_shutdown_wait);
-SYSCTL_INT(_hw_usb, OID_AUTO, no_shutdown_wait, CTLFLAG_RW|CTLFLAG_TUN, &usb_no_shutdown_wait, 0,
- "No USB device waiting at system shutdown.");
+SYSCTL_INT(_hw_usb, OID_AUTO, no_shutdown_wait, CTLFLAG_RW|CTLFLAG_TUN,
+ &usb_no_shutdown_wait, 0, "No USB device waiting at system shutdown.");
static devclass_t usb_devclass;
@@ -240,6 +245,11 @@ usb_suspend(device_t dev)
USB_BUS_LOCK(bus);
usb_proc_msignal(&bus->explore_proc,
&bus->suspend_msg[0], &bus->suspend_msg[1]);
+ if (usb_no_suspend_wait == 0) {
+ /* wait for suspend callback to be executed */
+ usb_proc_mwait(&bus->explore_proc,
+ &bus->suspend_msg[0], &bus->suspend_msg[1]);
+ }
USB_BUS_UNLOCK(bus);
return (0);
@@ -407,6 +417,15 @@ usb_bus_suspend(struct usb_proc_msg *pm)
USB_BUS_UNLOCK(bus);
+ /*
+ * We use the shutdown event here because the suspend and
+ * resume events are reserved for the USB port suspend and
+ * resume. The USB system suspend is implemented like full
+ * shutdown and all connected USB devices will be disconnected
+ * subsequently. At resume all USB devices will be
+ * re-connected again.
+ */
+
bus_generic_shutdown(bus->bdev);
usbd_enum_lock(udev);
OpenPOWER on IntegriCloud