svn commit: r226803 - in head/sys/dev/usb: . controller

Hans Petter Selasky hselasky at FreeBSD.org
Wed Oct 26 17:43:27 UTC 2011


Author: hselasky
Date: Wed Oct 26 17:43:27 2011
New Revision: 226803
URL: http://svn.freebsd.org/changeset/base/226803

Log:
  Fix suspend and resume of FULL and HIGH speed USB devices
  in the generic XHCI driver. There appears to be some minor
  logic missing for this feature to work.
  
  MFC after:	3 days

Modified:
  head/sys/dev/usb/controller/xhci.c
  head/sys/dev/usb/controller/xhcireg.h
  head/sys/dev/usb/usb.h
  head/sys/dev/usb/usb_hub.c

Modified: head/sys/dev/usb/controller/xhci.c
==============================================================================
--- head/sys/dev/usb/controller/xhci.c	Wed Oct 26 17:26:38 2011	(r226802)
+++ head/sys/dev/usb/controller/xhci.c	Wed Oct 26 17:43:27 2011	(r226803)
@@ -3048,7 +3048,9 @@ xhci_roothub_exec(struct usb_device *ude
 		}
 		port = XHCI_PORTSC(index);
 
-		v = XREAD4(sc, oper, port) & ~XHCI_PS_CLEAR;
+		v = XREAD4(sc, oper, port);
+		i = XHCI_PS_PLS_GET(v);
+		v &= ~XHCI_PS_CLEAR;
 
 		switch (value) {
 		case UHF_C_BH_PORT_RESET:
@@ -3082,6 +3084,17 @@ xhci_roothub_exec(struct usb_device *ude
 			XWRITE4(sc, oper, port, v & ~XHCI_PS_PIC_SET(3));
 			break;
 		case UHF_PORT_SUSPEND:
+
+			/* U3 -> U15 */
+			if (i == 3) {
+				XWRITE4(sc, oper, port, v |
+				    XHCI_PS_PLS_SET(0xF) | XHCI_PS_LWS);
+			}
+
+			/* wait 20ms for resume sequence to complete */
+			usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 50);
+
+			/* U0 */
 			XWRITE4(sc, oper, port, v |
 			    XHCI_PS_PLS_SET(0) | XHCI_PS_LWS);
 			break;

Modified: head/sys/dev/usb/controller/xhcireg.h
==============================================================================
--- head/sys/dev/usb/controller/xhcireg.h	Wed Oct 26 17:26:38 2011	(r226802)
+++ head/sys/dev/usb/controller/xhcireg.h	Wed Oct 26 17:43:27 2011	(r226803)
@@ -133,7 +133,7 @@
 #define	XHCI_PS_WOE		0x08000000	/* RW - wake on over-current enable */
 #define	XHCI_PS_DR		0x40000000	/* RO - device removable */
 #define	XHCI_PS_WPR		0x80000000U	/* RW - warm port reset */
-#define	XHCI_PS_CLEAR		0x80FF00F7U	/* command bits */
+#define	XHCI_PS_CLEAR		0x80FF01FFU	/* command bits */
 
 #define	XHCI_PORTPMSC(n)	(0x3F4 + (0x10 * (n)))	/* XHCI status and control */
 #define	XHCI_PM3_U1TO_GET(x)	(((x) >> 0) & 0xFF)	/* RW - U1 timeout */

Modified: head/sys/dev/usb/usb.h
==============================================================================
--- head/sys/dev/usb/usb.h	Wed Oct 26 17:26:38 2011	(r226802)
+++ head/sys/dev/usb/usb.h	Wed Oct 26 17:43:27 2011	(r226803)
@@ -686,6 +686,7 @@ struct usb_port_status {
 #define	UPS_PORT_LS_HOT_RST	0x09
 #define	UPS_PORT_LS_COMP_MODE	0x0A
 #define	UPS_PORT_LS_LOOPBACK	0x0B
+#define	UPS_PORT_LS_RESUME	0x0F
 #define	UPS_PORT_POWER			0x0100
 #define	UPS_LOW_SPEED			0x0200
 #define	UPS_HIGH_SPEED			0x0400

Modified: head/sys/dev/usb/usb_hub.c
==============================================================================
--- head/sys/dev/usb/usb_hub.c	Wed Oct 26 17:26:38 2011	(r226802)
+++ head/sys/dev/usb/usb_hub.c	Wed Oct 26 17:43:27 2011	(r226803)
@@ -611,6 +611,7 @@ uhub_suspend_resume_port(struct uhub_sof
 		switch (UPS_PORT_LINK_STATE_GET(sc->sc_st.port_status)) {
 		case UPS_PORT_LS_U0:
 		case UPS_PORT_LS_U1:
+		case UPS_PORT_LS_RESUME:
 			is_suspend = 0;
 			break;
 		default:


More information about the svn-src-all mailing list