tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

xhci patch 20150606



Hello,

Here are xhci patches of some fixes, comments, and
adding functions.

---
nh-usb_subr-ss.diff
	+ Use macro to check speed.
	  Forgotten in privious patch.
nh-xhcireg-maxintr.diff
	+ Fix num of Max Interrupters to 11 bits width.
nh-uhub-wrc.diff
	+ Simplify treatment of WRC condition and add comments.
nh-usb-kernhist.diff
	+ Add missing KERNHIST_LINK_STATIC(usbhist).
nh-bos.diff
	+ Read Binary Object Store descriptor and store to ud_bdesc.
nh-usbdi_util.diff
	+ Add usbd_set_port_u[12]_timeout().
nh-ssp.diff
	+ Add usbd_get_port_status_ext().
	+ Add some definitions for super speed plus.
	+ Update comments.


--
t-hash
--- usb_subr.c.0	2015-05-29 00:35:08.000000000 +0900
+++ usb_subr.c.1	2015-05-29 00:30:56.000000000 +0900
@@ -1428,10 +1428,11 @@ usbd_fill_deviceinfo(struct usbd_device 
 				else if (s & UPS_SUSPEND)
 					err = USB_PORT_SUSPENDED;
 				/*
-				 * UPS_PORT_POWER_SS is available only
-				 * if SS, otherwise it means UPS_LOW_SPEED.
+				 * Note: UPS_PORT_POWER_SS is available only
+				 * on 3.x, and UPS_PORT_POWER is available
+				 * only on 2.0 or 1.1.
 				 */
-				else if (dev->ud_speed == USB_SPEED_SUPER && 
+				else if (USB_IS_SS(dev->ud_speed) && 
 				    (s & UPS_PORT_POWER_SS))
 					err = USB_PORT_POWERED;
 				else if (s & UPS_PORT_POWER)
--- src/sys/dev/usb/xhcireg.h.orig	2015-04-07 01:29:02.000000000 +0900
+++ src/sys/dev/usb/xhcireg.h	2015-06-02 11:28:19.000000000 +0900
@@ -51,7 +51,7 @@
 #define	XHCI_HCIVERSION_1_0	0x0100	/* xHCI version 1.0 */
 #define	XHCI_HCSPARAMS1		0x04	/* RO structual parameters 1 */
 #define	XHCI_HCS1_MAXSLOTS(x)	((x) & 0xFF)
-#define	XHCI_HCS1_MAXINTRS(x)	(((x) >> 8) & 0x3FF)
+#define	XHCI_HCS1_MAXINTRS(x)	(((x) >> 8) & 0x7FF)
 #define	XHCI_HCS1_MAXPORTS(x)	(((x) >> 24) & 0xFF)
 #define	XHCI_HCSPARAMS2		0x08	/* RO structual parameters 2 */
 #define	XHCI_HCS2_IST(x)	((x) & 0xF)
--- src/sys/dev/usb/uhub.c.orig	2015-05-28 15:54:12.000000000 +0900
+++ src/sys/dev/usb/uhub.c	2015-06-03 11:57:34.000000000 +0900
@@ -586,11 +586,17 @@ uhub_explore(struct usbd_device *dev)
 					    port);
 			}
 		}
-		int is_wrc = 0;
-		if (change & UPS_C_PORT_RESET)
+		if (change & UPS_C_PORT_RESET) {
 			usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
+		}
 		if (change & UPS_C_BH_PORT_RESET) {
-			is_wrc = 1;
+			/*
+			 * some xHCs set WarmResetChange instead of CSC
+			 * when port is reset.
+			 */
+			if ((status & UPS_CURRENT_CONNECT_STATUS) != 0) {
+				change |= UPS_C_CONNECT_STATUS;
+			}
 			usbd_clear_port_feature(dev, port,
 			    UHF_C_BH_PORT_RESET);
 		}
@@ -603,9 +609,7 @@ uhub_explore(struct usbd_device *dev)
 
 		/* XXX handle overcurrent and resume events! */
 
-		/* xHCI sets WRC instead of CSC when port is reset */
-		if (!reconnect && !(change & UPS_C_CONNECT_STATUS) &&
-		    !(is_wrc && (status & UPS_CURRENT_CONNECT_STATUS))) {
+		if (!reconnect && !(change & UPS_C_CONNECT_STATUS)) {
 			/* No status change, just do recursive explore. */
 			if (up->up_dev != NULL && up->up_dev->ud_hub != NULL)
 				up->up_dev->ud_hub->uh_explore(up->up_dev);
--- src/sys/dev/usb/usb.c.orig	2015-05-29 02:06:38.000000000 +0900
+++ src/sys/dev/usb/usb.c	2015-05-31 15:45:07.000000000 +0900
@@ -276,6 +276,8 @@ usb_once_init(void)
 	struct usb_taskq *taskq;
 	int i;
 
+	KERNHIST_LINK_STATIC(usbhist);
+
 	selinit(&usb_selevent);
 	mutex_init(&usb_event_lock, MUTEX_DEFAULT, IPL_NONE);
 	cv_init(&usb_event_cv, "usbrea");
--- src/sys/dev/usb/usb_subr.c.orig	2015-05-29 00:30:56.000000000 +0900
+++ src/sys/dev/usb/usb_subr.c	2015-05-29 00:29:27.000000000 +0900
@@ -529,6 +529,7 @@ usbd_status
 usbd_set_config_index(struct usbd_device *dev, int index, int msg)
 {
 	usb_config_descriptor_t cd, *cdp;
+	usb_bos_descriptor_t bd, *bdp = NULL;
 	usbd_status err;
 	int i, ifcidx, nifc, len, selfpowered, power;
 
@@ -552,8 +553,12 @@ usbd_set_config_index(struct usbd_device
 			usbd_free_iface_data(dev, ifcidx);
 		kmem_free(dev->ud_ifaces, nifc * sizeof(struct usbd_interface));
 		kmem_free(dev->ud_cdesc, UGETW(dev->ud_cdesc->wTotalLength));
+		if (dev->ud_bdesc != NULL)
+			kmem_free(dev->ud_bdesc,
+			    UGETW(dev->ud_bdesc->wTotalLength));
 		dev->ud_ifaces = NULL;
 		dev->ud_cdesc = NULL;
+		dev->ud_bdesc = NULL;
 		dev->ud_config = USB_UNCONFIG_NO;
 	}
 
@@ -596,6 +601,41 @@ usbd_set_config_index(struct usbd_device
 		goto bad;
 	}
 
+	if (USB_IS_SS(dev->ud_speed)) {
+		int blen;
+
+		/* get short bos desc */
+		err = usbd_get_bos_desc(dev, index, &bd);
+		if (err) {
+			DPRINTF("get_bos_desc=%d", err, 0, 0, 0);
+			goto bad;
+		}
+		blen = UGETW(bd.wTotalLength);
+		bdp = kmem_alloc(blen, KM_SLEEP);
+		if (bdp == NULL) {
+			err = USBD_NOMEM;
+			goto bad;
+		}
+
+		/* Get the full desc */
+		for (i = 0; i < 3; i++) {
+			err = usbd_get_desc(dev, UDESC_BOS, index, blen, bdp);
+			if (!err)
+				break;
+			usbd_delay_ms(dev, 200);
+		}
+		if (err) {
+			DPRINTF("get_bos_desc=%d", err, 0, 0, 0);
+			goto bad;
+		}
+		if (bdp->bDescriptorType != UDESC_BOS) {
+			DPRINTF("bad desc %d", bdp->bDescriptorType, 0, 0, 0);
+			err = USBD_INVAL;
+			goto bad;
+		}
+	}
+	dev->ud_bdesc = bdp;
+
 	/*
 	 * Figure out if the device is self or bus powered.
 	 */
@@ -687,6 +727,10 @@ usbd_set_config_index(struct usbd_device
 
  bad:
 	kmem_free(cdp, len);
+	if (bdp != NULL) {
+		kmem_free(bdp, UGETW(bdp->wTotalLength));
+		dev->ud_bdesc = NULL;
+	}
 	return err;
 }
 
@@ -1532,6 +1576,8 @@ usb_free_device(struct usbd_device *dev)
 	}
 	if (dev->ud_cdesc != NULL)
 		kmem_free(dev->ud_cdesc, UGETW(dev->ud_cdesc->wTotalLength));
+	if (dev->ud_bdesc != NULL)
+		kmem_free(dev->ud_bdesc, UGETW(dev->ud_bdesc->wTotalLength));
 	if (dev->ud_subdevlen > 0) {
 		kmem_free(dev->ud_subdevs,
 		    dev->ud_subdevlen * sizeof(device_t));
--- src/sys/dev/usb/usbdivar.h.orig	2015-03-27 15:05:02.000000000 +0900
+++ src/sys/dev/usb/usbdivar.h	2015-05-28 10:16:46.000000000 +0900
@@ -195,6 +195,7 @@ struct usbd_device {
 	struct usbd_interface  *ud_ifaces;	/* array of all interfaces */
 	usb_device_descriptor_t ud_ddesc;	/* device descriptor */
 	usb_config_descriptor_t *ud_cdesc;	/* full config descr */
+	usb_bos_descriptor_t	*ud_bdesc;	/* full BOS descr */
 	const struct usbd_quirks     *ud_quirks;/* device quirks, always set */
 	struct usbd_hub	       *ud_hub;		/* only if this is a hub */
 	int			ud_subdevlen;	/* array length of following */
--- src/sys/dev/usb/usbdi_util.c.orig	2015-04-07 01:29:02.000000000 +0900
+++ src/sys/dev/usb/usbdi_util.c	2015-06-02 11:36:48.000000000 +0900
@@ -243,6 +243,32 @@ usbd_set_port_feature(struct usbd_device
 }
 
 usbd_status
+usbd_set_port_u1_timeout(struct usbd_device *dev, int port, int timeout)
+{
+	usb_device_request_t req;
+
+	req.bmRequestType = UT_WRITE_CLASS_OTHER;
+	req.bRequest = UR_SET_FEATURE;
+	USETW(req.wValue, UHF_PORT_U1_TIMEOUT);
+	USETW2(req.wIndex, timeout, port);
+	USETW(req.wLength, 0);
+	return usbd_do_request(dev, &req, 0);
+}
+
+usbd_status
+usbd_set_port_u2_timeout(struct usbd_device *dev, int port, int timeout)
+{
+	usb_device_request_t req;
+
+	req.bmRequestType = UT_WRITE_CLASS_OTHER;
+	req.bRequest = UR_SET_FEATURE;
+	USETW(req.wValue, UHF_PORT_U2_TIMEOUT);
+	USETW2(req.wIndex, timeout, port);
+	USETW(req.wLength, 0);
+	return usbd_do_request(dev, &req, 0);
+}
+
+usbd_status
 usbd_get_protocol(struct usbd_interface *iface, uint8_t *report)
 {
 	usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface);
--- src/sys/dev/usb/usbdi_util.h.orig	2015-04-07 01:29:02.000000000 +0900
+++ src/sys/dev/usb/usbdi_util.h	2015-06-02 11:34:43.000000000 +0900
@@ -52,6 +52,8 @@ usbd_status	usbd_set_hub_feature(struct 
 usbd_status	usbd_clear_hub_feature(struct usbd_device *, int);
 usbd_status	usbd_set_port_feature(struct usbd_device *, int, int);
 usbd_status	usbd_clear_port_feature(struct usbd_device *, int, int);
+usbd_status	usbd_set_port_u1_timeout(struct usbd_device *, int, int);
+usbd_status	usbd_set_port_u2_timeout(struct usbd_device *, int, int);
 usbd_status	usbd_get_device_status(struct usbd_device *, usb_status_t *);
 usbd_status	usbd_get_hub_status(struct usbd_device *, usb_hub_status_t *);
 usbd_status	usbd_get_protocol(struct usbd_interface *, uint8_t *);
--- src/sys/dev/usb/usbdi_util.c.orig	2015-04-07 01:29:02.000000000 +0900
+++ src/sys/dev/usb/usbdi_util.c	2015-06-02 11:36:48.000000000 +0900
@@ -190,6 +190,21 @@ usbd_get_port_status(struct usbd_device 
 	return usbd_do_request(dev, &req, ps);
 }
 
+/* USB 3.1 10.16.2.6, 10.16.2.6.3 */
+usbd_status
+usbd_get_port_status_ext(struct usbd_device *dev, int port,
+    usb_port_status_ext_t *pse)
+{
+	usb_device_request_t req;
+
+	req.bmRequestType = UT_READ_CLASS_OTHER;
+	req.bRequest = UR_GET_STATUS;
+	USETW2(req.wValue, 0, UR_PST_EXT_PORT_STATUS);
+	USETW(req.wIndex, port);
+	USETW(req.wLength, sizeof *pse);
+	return (usbd_do_request(dev, &req, pse));
+}
+
 usbd_status
 usbd_clear_hub_feature(struct usbd_device *dev, int sel)
 {
--- src/sys/dev/usb/usbdi_util.h.orig	2015-06-02 11:34:43.000000000 +0900
+++ src/sys/dev/usb/usbdi_util.h	2015-06-06 11:17:21.000000000 +0900
@@ -48,6 +48,8 @@ usbd_status	usbd_get_device_desc(struct 
 usbd_status	usbd_set_address(struct usbd_device *, int);
 usbd_status	usbd_get_port_status(struct usbd_device *,
 				     int, usb_port_status_t *);
+usbd_status	usbd_get_port_status_ext(struct usbd_device *,
+				     int, usb_port_status_ext_t *);
 usbd_status	usbd_set_hub_feature(struct usbd_device *, int);
 usbd_status	usbd_clear_hub_feature(struct usbd_device *, int);
 usbd_status	usbd_set_port_feature(struct usbd_device *, int, int);
--- src/sys/dev/usb/usb.h.orig	2015-05-28 15:54:12.000000000 +0900
+++ src/sys/dev/usb/usb.h	2015-06-02 11:38:22.000000000 +0900
@@ -395,15 +395,25 @@ typedef struct {
 } UPACKED usb_devcap_platform_descriptor_t;
 #define USB_DEVCAP_PLATFORM_DESCRIPTOR_SIZE 20
 
+/* usb 3.1 ch 9.6.2.4 */
 typedef struct {
 	uByte		bLength;
 	uByte		bDescriptorType;
 	uByte		bDevCapabilityType;
 	uByte		bReserved;
 	uDWord		bmAttributes;
+#define	XHCI_DEVCAP_SSP_SSAC(x)			__SHIFTOUT(x, __BITS(4,0))
+#define	XHCI_DEVCAP_SSP_SSIC(x)			__SHIFTOUT(x, __BITS(8,5))
 	uWord		wFunctionalitySupport;
+#define	XHCI_DEVCAP_SSP_SSID(x)			__SHIFTOUT(x, __BITS(3,0))
+#define	XHCI_DEVCAP_SSP_MIN_RXLANE_COUNT(x)	__SHIFTOUT(x, __BITS(11,8))
+#define	XHCI_DEVCAP_SSP_MIN_TXLANE_COUNT(x)	__SHIFTOUT(x, __BITS(15,12))
 	uWord		wReserved;
 	uDWord		bmSublinkSpeedAttr[0];
+#define	XHCI_DEVCAP_SSP_LSE(x)			__SHIFTOUT(x, __BITS(5,4))
+#define	XHCI_DEVCAP_SSP_ST(x)			__SHIFTOUT(x, __BITS(7,6))
+#define	XHCI_DEVCAP_SSP_LP(x)			__SHIFTOUT(x, __BITS(15,14))
+#define	XHCI_DEVCAP_SSP_LSM(x)			__SHIFTOUT(x, __BITS(31,16))
 } UPACKED usb_devcap_ssp_descriptor_t;
 #define USB_DEVCAP_SSP_DESCRIPTOR_SIZE 12 /* variable length */
 
@@ -424,6 +434,10 @@ typedef struct {
 #define UR_STOP_TT		0x0b
 #define UR_SET_HUB_DEPTH	0x0c
 #define UR_GET_PORT_ERR_COUNT	0x0d
+/* Port Status Type for GET_STATUS,  USB 3.1 10.16.2.6 and Table 10-12 */
+#define  UR_PST_PORT_STATUS	0
+#define  UR_PST_PD_STATUS	1
+#define  UR_PST_EXT_PORT_STATUS	2
 
 /*
  * Hub features from USB 2.0 spec, table 11-17 and updated by the
@@ -597,6 +611,14 @@ typedef struct {
 #define UPS_C_PORT_CONFIG_ERROR		0x0080
 } UPACKED usb_port_status_t;
 
+/* 10.16.2.6 */
+/* Valid when port status type is UR_PST_EXT_PORT_STATUS. */
+typedef struct {
+	uWord		wPortStatus;
+	uWord		wPortChange;
+	uDWord		dwExtPortStatus;
+} UPACKED usb_port_status_ext_t;
+
 /* Device class codes */
 #define UDCLASS_IN_INTERFACE	0x00
 #define UDCLASS_COMM		0x02
@@ -854,7 +876,8 @@ struct usb_device_info {
 #define USB_SPEED_FULL 2
 #define USB_SPEED_HIGH 3
 #define USB_SPEED_SUPER 4
-#define USB_IS_SS(X) ((X) == USB_SPEED_SUPER)
+#define USB_SPEED_SUPER_PLUS 5
+#define USB_IS_SS(X) ((X) == USB_SPEED_SUPER || (X) == USB_SPEED_SUPER_PLUS)
 	int		udi_power;	/* power consumption in mA, 0 if selfpowered */
 	int		udi_nports;
 	char		udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
--- src/sys/dev/usb/xhci.c.orig	2015-05-28 16:07:49.000000000 +0900
+++ src/sys/dev/usb/xhci.c	2015-06-06 14:01:46.000000000 +0900
@@ -1005,11 +1006,14 @@ xhci_intr1(struct xhci_softc * const sc)
  * port_status speed
  *	definition: UPS_*_SPEED in usb.h
  *	They are used in usb_port_status_t and valid only for USB 2.0.
- *	Speed value is 0 for Super Speed or more.
+ *	Speed value is always 0 for Super Speed or more, and dwExtPortStatus
+ *	of usb_port_status_ext_t indicates port speed.
  *	Note that some 3.0 values overlap with 2.0 values.
  *	(e.g. 0x200 means UPS_POER_POWER_SS in SS and
  *	            means UPS_LOW_SPEED in HS.)
- *	port status sent from hub also uses these values.
+ *	port status returned from hub also uses these values.
+ *	On NetBSD UPS_OTHER_SPEED indicates port speed is super speed
+ *	or more.
  * xspeed:
  *	definition: Protocol Speed ID (PSI) (xHCI 1.1 7.2.1)
  *	They are used in only slot context and PORTSC reg of xhci.


Home | Main Index | Thread Index | Old Index