Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 Aug 2010 14:59:17 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 182090 for review
Message-ID:  <201008081459.o78ExHsF013491@repoman.freebsd.org>

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

Change 182090 by hselasky@hselasky_laptop001 on 2010/08/08 14:58:42

	USB controller (XHCI):
		- more bugfixes

Affected files ...

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

Differences ...

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

@@ -652,7 +652,7 @@
 	status = XHCI_TRB_2_ERROR_GET(temp);
 
 	temp = le32toh(trb->dwTrb3);
-	epno = XHCI_TRB_3_EP_GET(temp) + 1;
+	epno = XHCI_TRB_3_EP_GET(temp);
 	index = XHCI_TRB_3_SLOT_GET(temp);
 
 	/* check if error means halted */
@@ -667,9 +667,7 @@
 		return;
 	}
 
-	epno++;
-
-	if (epno >= XHCI_MAX_ENDPOINTS) {
+	if ((epno == 0) || (epno >= XHCI_MAX_ENDPOINTS)) {
 		DPRINTF("Invalid endpoint.\n");
 		return;
 	}
@@ -688,14 +686,15 @@
 
 		td = xfer->td_transfer_cache;
 
-		DPRINTFN(5, "Checking if 0x%016llx == (0x%016llx .. 0x%016llx)\n",
+		DPRINTFN(5, "Checking if 0x%016llx == (0x%016llx .. 0x%016llx +/- 16)\n",
 			(long long)td_event,
 			(long long)td->td_self,
 			(long long)td->td_event_last);
 
 		if ((td_event == td->td_event_last) ||
+		    (td_event == (td->td_event_last - 16)) ||
 		    (halted && (td_event >= td->td_self) &&
-		    (td_event < td->td_event_last))) {
+		    (td_event <= td->td_event_last))) {
 
 			usb_pc_cpu_invalidate(td->page_cache);
 
@@ -1066,17 +1065,18 @@
 
 	switch (hdev->state) {
 	case XHCI_ST_ADDRESSED:
+	case XHCI_ST_CONFIGURED:
 		err = 0;
 		break;
 
-	case XHCI_ST_ENABLED:
+	case XHCI_ST_DEFAULT:
 		if (address == 0) {
 			err = 0;
 			break;
 		}
 		/* FALLTHROUGH */
 
-	case XHCI_ST_DEFAULT:
+	case XHCI_ST_ENABLED:
 
 		/* set configure mask to slot and EP0 */
 		xhci_configure_mask(udev, 3, 0);
@@ -1149,7 +1149,6 @@
 	return (err);
 }
 
-#if 0
 static usb_error_t
 xhci_cmd_configure_ep(struct xhci_softc *sc, uint64_t input_ctx,
     uint8_t deconfigure, uint8_t slot_id)
@@ -1171,7 +1170,6 @@
 
 	return (xhci_do_command(sc, &trb, 50 /* ms */));
 }
-#endif
 
 static usb_error_t
 xhci_cmd_evaluate_ctx(struct xhci_softc *sc, uint64_t input_ctx,
@@ -1546,7 +1544,7 @@
 		/* compute event pointer */
 
 		addr = td->td_self;
-		addr += (x - 1) * sizeof(struct xhci_trb);
+		addr += x * sizeof(struct xhci_trb);
 		td->td_event_last = addr;
 
 		/* fill out link TRB */
@@ -2046,8 +2044,16 @@
 			route |= rh_port;
 	}
 
-	temp = XHCI_SCTX_0_CTX_NUM_SET(XHCI_MAX_ENDPOINTS - 1) |
-	    XHCI_SCTX_0_ROUTE_SET(route);
+	temp = XHCI_SCTX_0_ROUTE_SET(route);
+
+	switch (sc->sc_hw.devs[index].state) {
+	case XHCI_ST_CONFIGURED:
+		temp |= XHCI_SCTX_0_CTX_NUM_SET(XHCI_MAX_ENDPOINTS - 1);
+		break;
+	default:
+		temp = XHCI_SCTX_0_CTX_NUM_SET(1);
+		break;
+	}
 
 	switch (udev->speed) {
 	case USB_SPEED_LOW:
@@ -2298,10 +2304,15 @@
 	uint64_t addr;
 	uint8_t i;
 	uint8_t inext;
+	uint8_t trb_limit;
+
+	DPRINTFN(8, "\n");
 
 	/* check if already inserted */
-	if (xfer->flags_int.bandwidth_reclaimed)
+	if (xfer->flags_int.bandwidth_reclaimed) {
+		DPRINTFN(8, "Already in schedule\n");
 		return (0);
+	}
 
 	pepext = xhci_get_endpoint_ext(xfer->xroot->udev,
 	    xfer->endpoint->edesc);
@@ -2310,7 +2321,19 @@
 	td_last = xfer->td_transfer_last;
 	addr = pepext->physaddr;
 
-	if (pepext->trb_used >= (XHCI_MAX_TRANSFERS - 1)) {
+	switch (xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
+	case UE_CONTROL:
+	case UE_INTERRUPT:
+		/* single buffered */
+		trb_limit = 1;
+		break;
+	default:
+		/* multi buffered */
+		trb_limit = (XHCI_MAX_TRANSFERS - 2);
+		break;
+	}
+
+	if (pepext->trb_used >= trb_limit) {
 		DPRINTFN(8, "Too many TDs queued.\n");
 		return (USB_ERR_NOMEM);
 	}
@@ -2331,6 +2354,8 @@
 	if (pepext->trb_running == 0) {
 		struct xhci_softc *sc = XHCI_BUS2SC(xfer->xroot->bus);
 
+		DPRINTFN(8, "Not running\n");
+
 		/* start configuration */
 		(void)usb_proc_msignal(&sc->sc_config_proc,
 		    &sc->sc_config_msg[0], &sc->sc_config_msg[1]);
@@ -2386,6 +2411,8 @@
 
 	usb_pc_cpu_flush(pepext->page_cache);
 
+	DPRINTF("qh_pos = %u\n", i);
+
 	pepext->xfer[i] = xfer;
 
 	xfer->qh_pos = i;
@@ -2396,6 +2423,10 @@
 
 	xhci_endpoint_doorbell(xfer);
 
+	/* start timeout, if any */
+	if (xfer->timeout != 0)
+		usbd_transfer_timeout_ms(xfer, &xhci_timeout, xfer->timeout);
+
 	return (0);
 }
 
@@ -2482,14 +2513,7 @@
 	DPRINTF("\n");
 
 	/* try to insert xfer on HW queue */
-	if (xhci_transfer_insert(xfer) != 0) {
-		DPRINTFN(0, "Failed to insert "
-		    "transfer %p into HW queue.\n", xfer);
-	}
-
-	/* start timeout, if any */
-	if (xfer->timeout != 0)
-		usbd_transfer_timeout_ms(xfer, &xhci_timeout, xfer->timeout);
+	xhci_transfer_insert(xfer);
 }
 
 struct usb_pipe_methods xhci_device_generic_methods =
@@ -3181,6 +3205,8 @@
 
 		struct usb_page_search buf_hub;
 
+		DPRINTF("Configure HUB\n");
+
 		usbd_get_page(&sc->sc_hw.devs[
 		    hub->controller_slot_id].input_pc, 0, &buf_hub);
 
@@ -3203,17 +3229,42 @@
 	err = xhci_configure_endpoint_by_xfer(xfer);
 
 	if (err == 0) {
-		err = xhci_cmd_stop_ep(sc, 0, epno - 1, index);
+
+		err = xhci_cmd_reset_ep(sc, 0, epno, index);
 
 		if (err != 0)
-			DPRINTF("Could not stop endpoint\n");
+			DPRINTF("Could not reset endpoint %u\n", epno);
+
+		if (epno > 1) {
+
+			err = xhci_cmd_stop_ep(sc, 0, epno, index);
+
+			if (err != 0)
+				DPRINTF("Could not stop endpoint %u\n", epno);
+
+			if (sc->sc_hw.devs[index].state != XHCI_ST_CONFIGURED) {
+				sc->sc_hw.devs[index].state = XHCI_ST_CONFIGURED;
+
+				xhci_configure_mask(udev, 1, 0);
+
+				err = xhci_configure_device(udev);
+
+				if (err != 0)
+					DPRINTF("Could not deconfigure device\n");
+
+				err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
+
+				if (err != 0)
+					DPRINTF("Could not evaluate device\n");
+			}
 
-		xhci_configure_mask(udev, 1U << epno, 1);
+			xhci_configure_mask(udev, 1U << epno, 1);
 
-		err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
+			err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
 
-		if (err != 0)
-			DPRINTF("Could not deconfigure endpoint %u\n", epno);
+			if (err != 0)
+				DPRINTF("Could not deconfigure endpoint %u\n", epno);
+		}
 
 		xhci_configure_mask(udev, 1U << epno, 0);
 
@@ -3221,20 +3272,20 @@
 
 		if (err != 0)
 			DPRINTF("Could not configure endpoint %u\n", epno);
+
+		err = xhci_cmd_configure_ep(sc, buf_inp.physaddr, 0, index);
+
+		if (err != 0)
+			DPRINTF("Could not configure endpoint %u\n", epno);
 	}
 
 	/* reset endpoint */
 
 	if (err == 0) {
-		if ((edesc->bmAttributes & UE_XFERTYPE) == UE_BULK)
-			err = xhci_cmd_reset_ep(sc, 0, epno - 1, index);
+		err = xhci_cmd_set_tr_dequeue_ptr(sc, pepext->physaddr |
+		    XHCI_EPCTX_2_DCS_SET(1), 0, epno, index);
 
 		if (err != 0)
-			DPRINTF("Could not reset endpoint %u\n", epno);
-
-		err = xhci_cmd_set_tr_dequeue_ptr(sc, pepext->physaddr, 0, epno - 1, index);
-
-		if (err != 0)
 			DPRINTF("Could not set dequeue ptr for endpoint %u\n", epno);
 	}
 	XHCI_CMD_UNLOCK(sc);
@@ -3302,7 +3353,7 @@
 			/* check if halted is still cleared */
 			if (pepext->trb_halted == 0) {
 				pepext->trb_running = 1;
-				pepext->trb_index = 1;
+				pepext->trb_index = 0;
 			}
 			goto restart;
 		}
@@ -3317,7 +3368,6 @@
 
 			/* queue changed - restart */
 			goto restart;
-
 		}
 	}
 



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