Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Aug 2010 18:25:52 GMT
From:      Hans Petter Selasky <hselasky@skunkworks.freebsd.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 182116 for review
Message-ID:  <201008111825.o7BIPq6X083820@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@182116?ac=10

Change 182116 by hselasky@hselasky_laptop001 on 2010/08/08 23:56:18

	
	USB controller (XHCI):
		- fix problem with multi enter of USB transfers.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#22 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#22 (text+ko) ====

@@ -1675,6 +1675,8 @@
 
 		x = XREAD4(temp.sc, runt, XHCI_MFINDEX);
 
+		DPRINTF("MFINDEX=0x%08x\n", x);
+
 		switch (usbd_get_speed(xfer->xroot->udev)) {
 		case USB_SPEED_FULL:
 			shift = 3;
@@ -2408,18 +2410,6 @@
 		return (USB_ERR_NOMEM);
 	}
 
-	/* check if transfer is not already on interrupt queue */
-	if (xfer->wait_queue != &xfer->xroot->bus->intr_q) {
-
-		/* remove transfer from pipe queue, if any */
-
-		usbd_transfer_dequeue(xfer);
-
-		/* add transfer last on interrupt queue */
-
-		usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
-	}
-
 	/* check for stopped condition, after putting transfer on interrupt queue */
 	if (pepext->trb_running == 0) {
 		struct xhci_softc *sc = XHCI_BUS2SC(xfer->xroot->bus);
@@ -2493,10 +2483,6 @@
 
 	xhci_endpoint_doorbell(xfer);
 
-	/* start timeout, if any */
-	if (xfer->timeout != 0)
-		usbd_transfer_timeout_ms(xfer, &xhci_timeout, xfer->timeout);
-
 	return (0);
 }
 
@@ -2566,6 +2552,42 @@
 }
 
 static void
+xhci_device_generic_multi_enter(struct usb_endpoint *ep,
+    struct usb_xfer *enter_xfer)
+{
+	struct usb_xfer *xfer;
+
+	/* check if there is a current transfer */
+	xfer = ep->endpoint_q.curr;
+	if (xfer == NULL)
+		return;
+
+	/*
+	 * Check if the current transfer is started and then pickup
+	 * the next one, if any. Else wait for next start event due to
+	 * block on failure feature.
+	 */
+	if (!xfer->flags_int.bandwidth_reclaimed)
+		return;
+
+	xfer = TAILQ_FIRST(&ep->endpoint_q.head);
+	if (xfer == NULL) {
+		/*
+		 * In case of enter we have to consider that the
+		 * transfer is queued by the USB core after the enter
+		 * method is called.
+		 */
+		xfer = enter_xfer;
+
+		if (xfer == NULL)
+			return;
+	}
+
+	/* try to multi buffer */
+	xhci_transfer_insert(xfer);
+}
+
+static void
 xhci_device_generic_enter(struct usb_xfer *xfer)
 {
 	DPRINTF("\n");
@@ -2573,8 +2595,7 @@
 	/* setup TD's and QH */
 	xhci_setup_generic_chain(xfer);
 
-	/* try to insert xfer on HW queue */
-	xhci_transfer_insert(xfer);
+	xhci_device_generic_multi_enter(xfer->endpoint, xfer);
 }
 
 static void
@@ -2584,6 +2605,16 @@
 
 	/* try to insert xfer on HW queue */
 	xhci_transfer_insert(xfer);
+
+	/* try to multi buffer */
+	xhci_device_generic_multi_enter(xfer->endpoint, NULL);
+
+	/* add transfer last on interrupt queue */
+	usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
+
+	/* start timeout, if any */
+	if (xfer->timeout != 0)
+		usbd_transfer_timeout_ms(xfer, &xhci_timeout, xfer->timeout);
 }
 
 struct usb_pipe_methods xhci_device_generic_methods =
@@ -2594,7 +2625,6 @@
 	.start = xhci_device_generic_start,
 };
 
-
 /*------------------------------------------------------------------------*
  * xhci root HUB support
  *------------------------------------------------------------------------*
@@ -3429,8 +3459,12 @@
 	}
 
 	TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
-			/* try to insert transfer in hardware schedule */
-			xhci_transfer_insert(xfer);
+
+		/* try to insert xfer on HW queue */
+		xhci_transfer_insert(xfer);
+
+		/* try to multi buffer */
+		xhci_device_generic_multi_enter(xfer->endpoint, NULL);
 	}
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008111825.o7BIPq6X083820>