svn commit: r278071 - in head/sys/dev/usb: . controller

Hans Petter Selasky hselasky at FreeBSD.org
Mon Feb 2 11:06:43 UTC 2015


Author: hselasky
Date: Mon Feb  2 11:06:41 2015
New Revision: 278071
URL: https://svnweb.freebsd.org/changeset/base/278071

Log:
  Section 3.2.9 in the XHCI specification about control transfers says
  that we should use a normal-TRB if there are more TRBs extending the
  data-stage TRB. Add a dedicated state bit to the internal USB transfer
  flags to handle this case.
  
  Reported by:	Kohji Okuno <okuno.kohji at jp.panasonic.com>
  MFC after:	1 week

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

Modified: head/sys/dev/usb/controller/xhci.c
==============================================================================
--- head/sys/dev/usb/controller/xhci.c	Mon Feb  2 10:31:35 2015	(r278070)
+++ head/sys/dev/usb/controller/xhci.c	Mon Feb  2 11:06:41 2015	(r278071)
@@ -1866,6 +1866,15 @@ restart:
 				    XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_DATA_STAGE);
 				if (temp->direction == UE_DIR_IN)
 					dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT;
+				/*
+				 * Section 3.2.9 in the XHCI
+				 * specification about control
+				 * transfers says that we should use a
+				 * normal-TRB if there are more TRBs
+				 * extending the data-stage
+				 * TRB. Update the "trb_type".
+				 */
+				temp->trb_type = XHCI_TRB_TYPE_NORMAL;
 				break;
 			case XHCI_TRB_TYPE_STATUS_STAGE:
 				dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
@@ -2106,7 +2115,8 @@ xhci_setup_generic_chain(struct usb_xfer
 		mult = 1;
 		temp.isoc_delta = 0;
 		temp.isoc_frame = 0;
-		temp.trb_type = XHCI_TRB_TYPE_DATA_STAGE;
+		temp.trb_type = xfer->flags_int.control_did_data ?
+		    XHCI_TRB_TYPE_NORMAL : XHCI_TRB_TYPE_DATA_STAGE;
 	} else {
 		x = 0;
 		mult = 1;

Modified: head/sys/dev/usb/usb_core.h
==============================================================================
--- head/sys/dev/usb/usb_core.h	Mon Feb  2 10:31:35 2015	(r278070)
+++ head/sys/dev/usb/usb_core.h	Mon Feb  2 11:06:41 2015	(r278071)
@@ -101,6 +101,7 @@ struct usb_xfer_flags_int {
 					 * sent */
 	uint8_t	control_act:1;		/* set if control transfer is active */
 	uint8_t	control_stall:1;	/* set if control transfer should be stalled */
+	uint8_t control_did_data:1;	/* set if control DATA has been transferred */
 
 	uint8_t	short_frames_ok:1;	/* filtered version */
 	uint8_t	short_xfer_ok:1;	/* filtered version */

Modified: head/sys/dev/usb/usb_transfer.c
==============================================================================
--- head/sys/dev/usb/usb_transfer.c	Mon Feb  2 10:31:35 2015	(r278070)
+++ head/sys/dev/usb/usb_transfer.c	Mon Feb  2 11:06:41 2015	(r278071)
@@ -1409,6 +1409,29 @@ usbd_control_transfer_init(struct usb_xf
 }
 
 /*------------------------------------------------------------------------*
+ *	usbd_control_transfer_did_data
+ *
+ * This function returns non-zero if a control endpoint has
+ * transferred the first DATA packet after the SETUP packet.
+ * Else it returns zero.
+ *------------------------------------------------------------------------*/
+static uint8_t
+usbd_control_transfer_did_data(struct usb_xfer *xfer)
+{
+	struct usb_device_request req;
+
+	/* SETUP packet is not yet sent */
+	if (xfer->flags_int.control_hdr != 0)
+		return (0);
+
+	/* copy out the USB request header */
+	usbd_copy_out(xfer->frbuffers, 0, &req, sizeof(req));
+
+	/* compare remainder to the initial value */
+	return (xfer->flags_int.control_rem != UGETW(req.wLength));
+}
+
+/*------------------------------------------------------------------------*
  *	usbd_setup_ctrl_transfer
  *
  * This function handles initialisation of control transfers. Control
@@ -1513,6 +1536,11 @@ usbd_setup_ctrl_transfer(struct usb_xfer
 		len = (xfer->sumlen - sizeof(struct usb_device_request));
 	}
 
+	/* update did data flag */
+
+	xfer->flags_int.control_did_data =
+	    usbd_control_transfer_did_data(xfer);
+
 	/* check if there is a length mismatch */
 
 	if (len > xfer->flags_int.control_rem) {


More information about the svn-src-head mailing list