Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 2 Jun 2013 10:32:58 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r251247 - head/sys/dev/usb/controller
Message-ID:  <201306021032.r52AWwWm021851@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Sun Jun  2 10:32:57 2013
New Revision: 251247
URL: http://svnweb.freebsd.org/changeset/base/251247

Log:
  Correct some XHCI streams mode transfer handling found by code inspection.
  The existing streams mode support is not working and has not been tested
  due to lack of hardware which supports the given feature.
  
  MFC after:	1 week

Modified:
  head/sys/dev/usb/controller/xhci.c
  head/sys/dev/usb/controller/xhci.h

Modified: head/sys/dev/usb/controller/xhci.c
==============================================================================
--- head/sys/dev/usb/controller/xhci.c	Sun Jun  2 10:19:14 2013	(r251246)
+++ head/sys/dev/usb/controller/xhci.c	Sun Jun  2 10:32:57 2013	(r251247)
@@ -133,8 +133,9 @@ static struct xhci_endpoint_ext *xhci_ge
 static usb_proc_callback_t xhci_configure_msg;
 static usb_error_t xhci_configure_device(struct usb_device *);
 static usb_error_t xhci_configure_endpoint(struct usb_device *,
-		    struct usb_endpoint_descriptor *, uint64_t, uint16_t,
-		    uint8_t, uint8_t, uint8_t, uint16_t, uint16_t, uint8_t);
+		   struct usb_endpoint_descriptor *, struct xhci_endpoint_ext *,
+		   uint16_t, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t,
+		   uint8_t);
 static usb_error_t xhci_configure_mask(struct usb_device *,
 		    uint32_t, uint8_t);
 static usb_error_t xhci_cmd_evaluate_ctx(struct xhci_softc *,
@@ -767,15 +768,17 @@ xhci_skip_transfer(struct usb_xfer *xfer
 static void
 xhci_check_transfer(struct xhci_softc *sc, struct xhci_trb *trb)
 {
+	struct xhci_endpoint_ext *pepext;
 	int64_t offset;
 	uint64_t td_event;
 	uint32_t temp;
 	uint32_t remainder;
+	uint16_t stream_id;
+	uint16_t i;
 	uint8_t status;
 	uint8_t halted;
 	uint8_t epno;
 	uint8_t index;
-	uint8_t i;
 
 	/* decode TRB */
 	td_event = le64toh(trb->qwTrb0);
@@ -783,6 +786,7 @@ xhci_check_transfer(struct xhci_softc *s
 
 	remainder = XHCI_TRB_2_REM_GET(temp);
 	status = XHCI_TRB_2_ERROR_GET(temp);
+	stream_id = XHCI_TRB_2_STREAM_GET(temp);
 
 	temp = le32toh(trb->dwTrb3);
 	epno = XHCI_TRB_3_EP_GET(temp);
@@ -792,8 +796,8 @@ xhci_check_transfer(struct xhci_softc *s
 	halted = (status != XHCI_TRB_ERROR_SHORT_PKT &&
 	    status != XHCI_TRB_ERROR_SUCCESS);
 
-	DPRINTF("slot=%u epno=%u remainder=%u status=%u\n",
-	    index, epno, remainder, status);
+	DPRINTF("slot=%u epno=%u stream=%u remainder=%u status=%u\n",
+	    index, epno, stream_id, remainder, status);
 
 	if (index > sc->sc_noslot) {
 		DPRINTF("Invalid slot.\n");
@@ -805,15 +809,22 @@ xhci_check_transfer(struct xhci_softc *s
 		return;
 	}
 
+	pepext = &sc->sc_hw.devs[index].endp[epno];
+
+	if (pepext->trb_ep_mode != USB_EP_MODE_STREAMS) {
+		stream_id = 0;
+		DPRINTF("stream_id=0\n");
+	} else if (stream_id >= XHCI_MAX_STREAMS) {
+		DPRINTF("Invalid stream ID.\n");
+		return;
+	}
+
 	/* try to find the USB transfer that generated the event */
 	for (i = 0; i != (XHCI_MAX_TRANSFERS - 1); i++) {
 		struct usb_xfer *xfer;
 		struct xhci_td *td;
-		struct xhci_endpoint_ext *pepext;
 
-		pepext = &sc->sc_hw.devs[index].endp[epno];
-
-		xfer = pepext->xfer[i];
+		xfer = pepext->xfer[i + (XHCI_MAX_TRANSFERS * stream_id)];
 		if (xfer == NULL)
 			continue;
 
@@ -1265,7 +1276,7 @@ xhci_set_address(struct usb_device *udev
 		pepext = xhci_get_endpoint_ext(udev,
 		    &udev->ctrl_ep_desc);
 		err = xhci_configure_endpoint(udev,
-		    &udev->ctrl_ep_desc, pepext->physaddr,
+		    &udev->ctrl_ep_desc, pepext,
 		    0, 1, 1, 0, mps, mps, USB_EP_MODE_DEFAULT);
 
 		if (err != 0) {
@@ -2104,14 +2115,15 @@ xhci_configure_mask(struct usb_device *u
 
 static usb_error_t
 xhci_configure_endpoint(struct usb_device *udev,
-    struct usb_endpoint_descriptor *edesc, uint64_t ring_addr,
-    uint16_t interval, uint8_t max_packet_count, uint8_t mult,
-    uint8_t fps_shift, uint16_t max_packet_size,
+    struct usb_endpoint_descriptor *edesc, struct xhci_endpoint_ext *pepext,
+    uint16_t interval, uint8_t max_packet_count,
+    uint8_t mult, uint8_t fps_shift, uint16_t max_packet_size,
     uint16_t max_frame_size, uint8_t ep_mode)
 {
 	struct usb_page_search buf_inp;
 	struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
 	struct xhci_input_dev_ctx *pinp;
+	uint64_t ring_addr = pepext->physaddr;
 	uint32_t temp;
 	uint8_t index;
 	uint8_t epno;
@@ -2142,6 +2154,10 @@ xhci_configure_endpoint(struct usb_devic
 	if (mult == 0)
 		return (USB_ERR_BAD_BUFSIZE);
 
+	/* store endpoint mode */
+	pepext->trb_ep_mode = ep_mode;
+	usb_pc_cpu_flush(pepext->page_cache);
+
 	if (ep_mode == USB_EP_MODE_STREAMS) {
 		temp = XHCI_EPCTX_0_EPSTATE_SET(0) |
 		    XHCI_EPCTX_0_MAXP_STREAMS_SET(XHCI_MAX_STREAMS_LOG - 1) |
@@ -2286,7 +2302,7 @@ xhci_configure_endpoint_by_xfer(struct u
 	usb_pc_cpu_flush(pepext->page_cache);
 
 	return (xhci_configure_endpoint(xfer->xroot->udev,
-	    xfer->endpoint->edesc, pepext->physaddr,
+	    xfer->endpoint->edesc, pepext,
 	    xfer->interval, xfer->max_packet_count,
 	    (ecomp != NULL) ? UE_GET_SS_ISO_MULT(ecomp->bmAttributes) + 1 : 1,
 	    usbd_xfer_get_fps_shift(xfer), xfer->max_packet_size,
@@ -2701,6 +2717,9 @@ xhci_transfer_insert(struct usb_xfer *xf
 	if (inext >= (XHCI_MAX_TRANSFERS - 1))
 		inext = 0;
 
+	/* store next TRB index, before stream ID offset is added */
+	pepext->trb_index[id] = inext;
+
 	/* offset for stream */
 	i += id * XHCI_MAX_TRANSFERS;
 	inext += id * XHCI_MAX_TRANSFERS;
@@ -2750,8 +2769,6 @@ xhci_transfer_insert(struct usb_xfer *xf
 
 	xfer->flags_int.bandwidth_reclaimed = 1;
 
-	pepext->trb_index[id] = inext;
-
 	xhci_endpoint_doorbell(xfer);
 
 	return (0);
@@ -3674,7 +3691,7 @@ restart:
 		if ((pepext->trb_halted != 0) ||
 		    (pepext->trb_running == 0)) {
 
-			uint8_t i;
+			uint16_t i;
 
 			/* clear halted and running */
 			pepext->trb_halted = 0;
@@ -3682,7 +3699,8 @@ restart:
 
 			/* nuke remaining buffered transfers */
 
-			for (i = 0; i != (XHCI_MAX_TRANSFERS - 1); i++) {
+			for (i = 0; i != (XHCI_MAX_TRANSFERS *
+			    XHCI_MAX_STREAMS); i++) {
 				/*
 				 * NOTE: We need to use the timeout
 				 * error code here else existing

Modified: head/sys/dev/usb/controller/xhci.h
==============================================================================
--- head/sys/dev/usb/controller/xhci.h	Sun Jun  2 10:19:14 2013	(r251246)
+++ head/sys/dev/usb/controller/xhci.h	Sun Jun  2 10:32:57 2013	(r251247)
@@ -369,6 +369,7 @@ struct xhci_endpoint_ext {
 	uint8_t			trb_index[XHCI_MAX_STREAMS];
 	uint8_t			trb_halted;
 	uint8_t			trb_running;
+	uint8_t			trb_ep_mode;
 };
 
 enum {



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