svn commit: r215949 - stable/8/sys/dev/usb/controller

Andrew Thompson thompsa at FreeBSD.org
Sat Nov 27 19:47:59 UTC 2010


Author: thompsa
Date: Sat Nov 27 19:47:58 2010
New Revision: 215949
URL: http://svn.freebsd.org/changeset/base/215949

Log:
  MFC r213857,213861,213864,213869,213871
  
   EHCI fixes for register and TD handling.

Modified:
  stable/8/sys/dev/usb/controller/ehci.c
  stable/8/sys/dev/usb/controller/ehci.h
  stable/8/sys/dev/usb/controller/ehci_pci.c
  stable/8/sys/dev/usb/controller/ehcireg.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/mips/alchemy/   (props changed)
  stable/8/sys/mips/atheros/   (props changed)
  stable/8/sys/mips/cavium/   (props changed)
  stable/8/sys/mips/cavium/dev/   (props changed)
  stable/8/sys/mips/rmi/   (props changed)
  stable/8/sys/mips/rmi/dev/   (props changed)
  stable/8/sys/mips/sibyte/   (props changed)

Modified: stable/8/sys/dev/usb/controller/ehci.c
==============================================================================
--- stable/8/sys/dev/usb/controller/ehci.c	Sat Nov 27 19:40:51 2010	(r215948)
+++ stable/8/sys/dev/usb/controller/ehci.c	Sat Nov 27 19:47:58 2010	(r215949)
@@ -145,7 +145,6 @@ struct ehci_std_temp {
 	uint8_t	auto_data_toggle;
 	uint8_t	setup_alt_next;
 	uint8_t	last_frame;
-	uint8_t can_use_next;
 };
 
 void
@@ -157,6 +156,9 @@ ehci_iterate_hw_softc(struct usb_bus *bu
 	cb(bus, &sc->sc_hw.pframes_pc, &sc->sc_hw.pframes_pg,
 	    sizeof(uint32_t) * EHCI_FRAMELIST_COUNT, EHCI_FRAMELIST_ALIGN);
 
+	cb(bus, &sc->sc_hw.terminate_pc, &sc->sc_hw.terminate_pg,
+	    sizeof(struct ehci_qh_sub), EHCI_QH_ALIGN);
+
 	cb(bus, &sc->sc_hw.async_start_pc, &sc->sc_hw.async_start_pg,
 	    sizeof(ehci_qh_t), EHCI_QH_ALIGN);
 
@@ -310,6 +312,24 @@ ehci_init(ehci_softc_t *sc)
 
 	sc->sc_eintrs = EHCI_NORMAL_INTRS;
 
+	if (1) {
+		struct ehci_qh_sub *qh;
+
+		usbd_get_page(&sc->sc_hw.terminate_pc, 0, &buf_res);
+
+		qh = buf_res.buffer;
+
+		sc->sc_terminate_self = htohc32(sc, buf_res.physaddr);
+
+		/* init terminate TD */
+		qh->qtd_next =
+		    htohc32(sc, EHCI_LINK_TERMINATE);
+		qh->qtd_altnext =
+		    htohc32(sc, EHCI_LINK_TERMINATE);
+		qh->qtd_status =
+		    htohc32(sc, EHCI_QTD_HALTED);
+	}
+
 	for (i = 0; i < EHCI_VIRTUAL_FRAMELIST_COUNT; i++) {
 		ehci_qh_t *qh;
 
@@ -1416,15 +1436,7 @@ ehci_check_transfer(struct usb_xfer *xfe
 			 */
 			if (status & EHCI_QTD_ACTIVE) {
 				/* update cache */
-				if (xfer->td_transfer_cache != td) {
-					xfer->td_transfer_cache = td;
-					if (qh->qh_qtd.qtd_next & 
-					    htohc32(sc, EHCI_LINK_TERMINATE)) {
-						/* XXX - manually advance to next frame */
-						qh->qh_qtd.qtd_next = td->qtd_self;
-						usb_pc_cpu_flush(td->page_cache);
-					}
-				}
+				xfer->td_transfer_cache = td;
 				goto done;
 			}
 			/*
@@ -1634,10 +1646,12 @@ ehci_setup_standard_chain_sub(struct ehc
 	uint32_t average;
 	uint32_t len_old;
 	uint32_t terminate;
+	uint32_t qtd_altnext;
 	uint8_t shortpkt_old;
 	uint8_t precompute;
 
-	terminate = htohc32(temp->sc, EHCI_LINK_TERMINATE);
+	terminate = temp->sc->sc_terminate_self;
+	qtd_altnext = temp->sc->sc_terminate_self;
 	td_alt_next = NULL;
 	buf_offset = 0;
 	shortpkt_old = temp->shortpkt;
@@ -1771,23 +1785,11 @@ restart:
 			td->qtd_buffer_hi[x] = 0;
 		}
 
-		if (temp->can_use_next) {
-			if (td_next) {
-				/* link the current TD with the next one */
-				td->qtd_next = td_next->qtd_self;
-			}
-		} else {
-			/*
-			 * BUG WARNING: The EHCI HW can use the
-			 * qtd_next field instead of qtd_altnext when
-			 * a short packet is received! We work this
-			 * around in software by not queueing more
-			 * than one job/TD at a time!
-			 */
-			td->qtd_next = terminate;
+		if (td_next) {
+			/* link the current TD with the next one */
+			td->qtd_next = td_next->qtd_self;
 		}
-
-		td->qtd_altnext = terminate;
+		td->qtd_altnext = qtd_altnext;
 		td->alt_next = td_alt_next;
 
 		usb_pc_cpu_flush(td->page_cache);
@@ -1799,9 +1801,15 @@ restart:
 		/* setup alt next pointer, if any */
 		if (temp->last_frame) {
 			td_alt_next = NULL;
+			qtd_altnext = terminate;
 		} else {
 			/* we use this field internally */
 			td_alt_next = td_next;
+			if (temp->setup_alt_next) {
+				qtd_altnext = td_next->qtd_self;
+			} else {
+				qtd_altnext = terminate;
+			}
 		}
 
 		/* restore */
@@ -1846,8 +1854,6 @@ ehci_setup_standard_chain(struct usb_xfe
 	temp.qtd_status = 0;
 	temp.last_frame = 0;
 	temp.setup_alt_next = xfer->flags_int.short_frames_ok;
-	temp.can_use_next = (xfer->flags_int.control_xfr ||
-	    (UE_GET_DIR(xfer->endpointno) == UE_DIR_OUT));
 
 	if (xfer->flags_int.control_xfr) {
 		if (xfer->endpoint->toggle_next) {
@@ -1860,7 +1866,8 @@ ehci_setup_standard_chain(struct usb_xfe
 		temp.auto_data_toggle = 1;
 	}
 
-	if (usbd_get_speed(xfer->xroot->udev) != USB_SPEED_HIGH) {
+	if ((xfer->xroot->udev->parent_hs_hub != NULL) ||
+	    (xfer->xroot->udev->address != 0)) {
 		/* max 3 retries */
 		temp.qtd_status |=
 		    htohc32(temp.sc, EHCI_QTD_SET_CERR(3));
@@ -3063,8 +3070,7 @@ static const struct ehci_config_desc ehc
 		.bNumEndpoints = 1,
 		.bInterfaceClass = UICLASS_HUB,
 		.bInterfaceSubClass = UISUBCLASS_HUB,
-		.bInterfaceProtocol = UIPROTO_HSHUBSTT,
-		0
+		.bInterfaceProtocol = 0,
 	},
 	.endpd = {
 		.bLength = sizeof(struct usb_endpoint_descriptor),
@@ -3114,7 +3120,6 @@ ehci_roothub_exec(struct usb_device *ude
 	uint16_t i;
 	uint16_t value;
 	uint16_t index;
-	uint8_t l;
 	usb_error_t err;
 
 	USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
@@ -3318,20 +3323,23 @@ ehci_roothub_exec(struct usb_device *ude
 			err = USB_ERR_IOERROR;
 			goto done;
 		}
-		v = EOREAD4(sc, EHCI_HCSPARAMS);
+		v = EREAD4(sc, EHCI_HCSPARAMS);
 
 		sc->sc_hub_desc.hubd = ehci_hubd;
 		sc->sc_hub_desc.hubd.bNbrPorts = sc->sc_noport;
-		USETW(sc->sc_hub_desc.hubd.wHubCharacteristics,
-		    (EHCI_HCS_PPC(v) ? UHD_PWR_INDIVIDUAL : UHD_PWR_NO_SWITCH) |
-		    (EHCI_HCS_P_INDICATOR(EREAD4(sc, EHCI_HCSPARAMS)) ?
-		    UHD_PORT_IND : 0));
+
+		if (EHCI_HCS_PPC(v))
+			i = UHD_PWR_INDIVIDUAL;
+		else
+			i = UHD_PWR_NO_SWITCH;
+
+		if (EHCI_HCS_P_INDICATOR(v))
+			i |= UHD_PORT_IND;
+
+		USETW(sc->sc_hub_desc.hubd.wHubCharacteristics, i);
 		/* XXX can't find out? */
 		sc->sc_hub_desc.hubd.bPwrOn2PwrGood = 200;
-		for (l = 0; l < sc->sc_noport; l++) {
-			/* XXX can't find out? */
-			sc->sc_hub_desc.hubd.DeviceRemovable[l / 8] &= ~(1 << (l % 8));
-		}
+		/* XXX don't know if ports are removable or not */
 		sc->sc_hub_desc.hubd.bDescLength =
 		    8 + ((sc->sc_noport + 7) / 8);
 		len = sc->sc_hub_desc.hubd.bDescLength;

Modified: stable/8/sys/dev/usb/controller/ehci.h
==============================================================================
--- stable/8/sys/dev/usb/controller/ehci.h	Sat Nov 27 19:40:51 2010	(r215948)
+++ stable/8/sys/dev/usb/controller/ehci.h	Sat Nov 27 19:47:58 2010	(r215949)
@@ -292,12 +292,14 @@ typedef struct ehci_fstn ehci_fstn_t;
 
 struct ehci_hw_softc {
 	struct usb_page_cache pframes_pc;
+	struct usb_page_cache terminate_pc;
 	struct usb_page_cache async_start_pc;
 	struct usb_page_cache intr_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT];
 	struct usb_page_cache isoc_hs_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT];
 	struct usb_page_cache isoc_fs_start_pc[EHCI_VIRTUAL_FRAMELIST_COUNT];
 
 	struct usb_page pframes_pg;
+	struct usb_page terminate_pg;
 	struct usb_page async_start_pg;
 	struct usb_page intr_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT];
 	struct usb_page isoc_hs_start_pg[EHCI_VIRTUAL_FRAMELIST_COUNT];
@@ -336,6 +338,7 @@ typedef struct ehci_softc {
 	bus_space_tag_t sc_io_tag;
 	bus_space_handle_t sc_io_hdl;
 
+	uint32_t sc_terminate_self;	/* TD short packet termination pointer */
 	uint32_t sc_eintrs;
 	uint32_t sc_cmd;		/* shadow of cmd register during
 					 * suspend */

Modified: stable/8/sys/dev/usb/controller/ehci_pci.c
==============================================================================
--- stable/8/sys/dev/usb/controller/ehci_pci.c	Sat Nov 27 19:40:51 2010	(r215948)
+++ stable/8/sys/dev/usb/controller/ehci_pci.c	Sat Nov 27 19:47:58 2010	(r215949)
@@ -100,8 +100,6 @@ __FBSDID("$FreeBSD$");
 #define	PCI_EHCI_VENDORID_NVIDIA2	0x10DE
 #define	PCI_EHCI_VENDORID_VIA		0x1106
 
-#define	PCI_EHCI_BASE_REG	0x10
-
 static void ehci_pci_takecontroller(device_t self);
 
 static device_probe_t ehci_pci_probe;

Modified: stable/8/sys/dev/usb/controller/ehcireg.h
==============================================================================
--- stable/8/sys/dev/usb/controller/ehcireg.h	Sat Nov 27 19:40:51 2010	(r215948)
+++ stable/8/sys/dev/usb/controller/ehcireg.h	Sat Nov 27 19:47:58 2010	(r215949)
@@ -14,13 +14,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED


More information about the svn-src-all mailing list