tech-kern archive

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

[patch] xhci patch 20151003



Hello,

Here is an xhci patch for nick-nhusb branch.


nhusb-uhub_c.diff
	+ Import port speed detection code from OpenBSD.
	  Check port power bit instead of speed bits. It's a cool idea.
	+ Fix bus revision of xhci.


Thanks,
--
t-hash
--- sys/dev/usb/uhub.c.orig	2015-09-23 23:15:16.000000000 +0900
+++ sys/dev/usb/uhub.c	2015-09-28 06:38:39.000000000 +0900
@@ -1,5 +1,6 @@
 /*	$NetBSD: uhub.c,v 1.126.2.14 2015/09/23 13:49:59 skrll Exp $	*/
 /*	$FreeBSD: src/sys/dev/usb/uhub.c,v 1.18 1999/11/17 22:33:43 n_hibma Exp $	*/
+/*	$OpenBSD: uhub.c,v 1.86 2015/06/29 18:27:40 mpi Exp $ */
 
 /*
  * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
@@ -546,10 +547,6 @@ uhub_explore(struct usbd_device *dev)
 			}
 			status = UGETW(up->up_status.wPortStatus);
 			change = UGETW(up->up_status.wPortChange);
-			if (USB_IS_SS(dev->ud_speed)) {
-				status |= UPS_OTHER_SPEED;
-				USETW(up->up_status.wPortStatus, status);
-			}
 
 			DPRINTF("uhub %d port %d: s/c=%x/%x",
 			    device_unit(sc->sc_dev), port, status, change);
@@ -661,23 +658,6 @@ uhub_explore(struct usbd_device *dev)
 		DPRINTF("unit %d dev->speed=%u dev->depth=%u",
 		    device_unit(sc->sc_dev), dev->ud_speed, dev->ud_depth, 0);
 
-		/*
-		 * To check whether port has power,
-		 *  check UPS_PORT_POWER bit if port speed is HS/FS/LS and
-		 *  check UPS_PORT_POWER_SS bit if port speed is SS.
-		 */
-		if (status & UPS_OTHER_SPEED) {
-			if (!(status & UPS_PORT_POWER_SS))
-				aprint_normal_dev(sc->sc_dev,
-				    "strange, connected port %d has no power\n",
-				    port);
-		} else {
-			if (!(status & UPS_PORT_POWER))
-				aprint_normal_dev(sc->sc_dev,
-				    "strange, connected port %d has no power\n",
-				    port);
-		}
-
 		/* Wait for maximum device power up time. */
 		usbd_delay_ms(dev, USB_PORT_POWERUP_DELAY);
 
@@ -696,10 +676,6 @@ uhub_explore(struct usbd_device *dev)
 		}
 		status = UGETW(up->up_status.wPortStatus);
 		change = UGETW(up->up_status.wPortChange);
-		if (USB_IS_SS(dev->ud_speed)) {
-			status |= UPS_OTHER_SPEED;
-			USETW(up->up_status.wPortStatus, status);
-		}
 		DPRINTF("hub %d port %d after reset: s/c=%x/%x",
 		    device_unit(sc->sc_dev), port, status, change);
 
@@ -724,19 +700,60 @@ uhub_explore(struct usbd_device *dev)
 			usbd_clear_port_feature(dev, port,
 			    UHF_C_BH_PORT_RESET);
 
-		/* Figure out device speed */
-		if (status & UPS_OTHER_SPEED) {
-			speed = USB_SPEED_SUPER;
-		} else if (status & UPS_HIGH_SPEED)
+		/*
+		 * Figure out device speed from power bit of port status.
+		 *  USB 2.0 ch 11.24.2.7.1
+		 *  USB 3.1 ch 10.16.2.6.1
+		 */
+		int sts = status;
+		if ((sts & UPS_PORT_POWER) == 0)
+			sts &= ~UPS_PORT_POWER_SS;
+
+		if (sts & UPS_HIGH_SPEED)
 			speed = USB_SPEED_HIGH;
-		else if (status & UPS_LOW_SPEED)
+		else if (sts & UPS_LOW_SPEED)
 			speed = USB_SPEED_LOW;
-		else
-			speed = USB_SPEED_FULL;
+		else {
+			/*
+			 * If there is no power bit set, it is certainly
+			 * a Super Speed device, so use the speed of its
+			 * parent hub.
+			 */
+			if (sts & UPS_PORT_POWER)
+				speed = USB_SPEED_FULL;
+			else
+				speed = dev->ud_speed;
+		}
+
+		/*
+		 * Reduce the speed, otherwise we won't setup the proper
+		 * transfer methods.
+		 */
+		if (speed > dev->ud_speed)
+			speed = dev->ud_speed;
 
 		DPRINTF("uhub %d speed %u", device_unit(sc->sc_dev), speed, 0,
 		    0);
 
+		/*
+		 * To check whether port has power,
+		 *  check UPS_PORT_POWER_SS bit if port speed is SS, and
+		 *  check UPS_PORT_POWER bit if port speed is HS/FS/LS.
+		 */
+		if (USB_IS_SS(speed)) {
+			/* SS hub port */
+			if (!(status & UPS_PORT_POWER_SS))
+				aprint_normal_dev(sc->sc_dev,
+				    "strange, connected port %d has no power\n",
+				    port);
+		} else {
+			/* HS/FS/LS hub port */
+			if (!(status & UPS_PORT_POWER))
+				aprint_normal_dev(sc->sc_dev,
+				    "strange, connected port %d has no power\n",
+				    port);
+		}
+
 		/* Get device info and set its address. */
 		err = usbd_new_device(sc->sc_dev, dev->ud_bus,
 			  dev->ud_depth + 1, speed, port, up);
--- sys/dev/usb/xhci.c.orig	2015-09-23 23:15:19.000000000 +0900
+++ sys/dev/usb/xhci.c	2015-09-26 08:56:50.000000000 +0900
@@ -662,7 +662,7 @@ xhci_init(struct xhci_softc *sc)
 	XHCIHIST_FUNC(); XHCIHIST_CALLED();
 
 	/* XXX Low/Full/High speeds for now */
-	sc->sc_bus.ub_revision = USBREV_2_0;
+	sc->sc_bus.ub_revision = USBREV_3_0;
 	sc->sc_bus.ub_usedma = true;
 
 	cap = xhci_read_4(sc, XHCI_CAPLENGTH);


Home | Main Index | Thread Index | Old Index