Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 May 2009 17:39:21 +0000 (UTC)
From:      Andrew Thompson <thompsa@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r192552 - in head/sys/dev/usb: . controller
Message-ID:  <200905211739.n4LHdLjM073793@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: thompsa
Date: Thu May 21 17:39:21 2009
New Revision: 192552
URL: http://svn.freebsd.org/changeset/base/192552

Log:
  Improve device mode (gadget) stall handling.
  
  Some hardware easily comes out of sync with regard to whether the current or
  the next control transfer should be stalled, if a stall command is always
  issued before receiving the SETUP packet. After this patch the stall command
  will only be issued when a transfer should actually be stalled.
  
  Submitted by:	Hans Petter Selasky

Modified:
  head/sys/dev/usb/controller/at91dci.c
  head/sys/dev/usb/controller/at91dci.h
  head/sys/dev/usb/controller/atmegadci.c
  head/sys/dev/usb/controller/atmegadci.h
  head/sys/dev/usb/controller/musb_otg.c
  head/sys/dev/usb/controller/musb_otg.h
  head/sys/dev/usb/controller/uss820dci.c
  head/sys/dev/usb/controller/uss820dci.h
  head/sys/dev/usb/usb_core.h
  head/sys/dev/usb/usb_transfer.c

Modified: head/sys/dev/usb/controller/at91dci.c
==============================================================================
--- head/sys/dev/usb/controller/at91dci.c	Thu May 21 17:26:20 2009	(r192551)
+++ head/sys/dev/usb/controller/at91dci.c	Thu May 21 17:39:21 2009	(r192552)
@@ -848,7 +848,7 @@ at91dci_setup_standard_chain_sub(struct 
 	td->remainder = temp->len;
 	td->fifo_bank = 0;
 	td->error = 0;
-	td->did_stall = 0;
+	td->did_stall = temp->did_stall;
 	td->short_pkt = temp->short_pkt;
 	td->alt_next = temp->setup_alt_next;
 }
@@ -879,6 +879,7 @@ at91dci_setup_standard_chain(struct usb2
 	temp.td_next = xfer->td_start[0];
 	temp.offset = 0;
 	temp.setup_alt_next = xfer->flags_int.short_frames_ok;
+	temp.did_stall = !xfer->flags_int.control_stall;
 
 	sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
 	ep_no = (xfer->endpoint & UE_ADDR);

Modified: head/sys/dev/usb/controller/at91dci.h
==============================================================================
--- head/sys/dev/usb/controller/at91dci.h	Thu May 21 17:26:20 2009	(r192551)
+++ head/sys/dev/usb/controller/at91dci.h	Thu May 21 17:39:21 2009	(r192552)
@@ -169,6 +169,7 @@ struct at91dci_std_temp {
          * short_pkt = 1: transfer should not be short terminated
          */
 	uint8_t	setup_alt_next;
+	uint8_t did_stall;
 };
 
 struct at91dci_config_desc {

Modified: head/sys/dev/usb/controller/atmegadci.c
==============================================================================
--- head/sys/dev/usb/controller/atmegadci.c	Thu May 21 17:26:20 2009	(r192551)
+++ head/sys/dev/usb/controller/atmegadci.c	Thu May 21 17:39:21 2009	(r192552)
@@ -751,7 +751,7 @@ atmegadci_setup_standard_chain_sub(struc
 	td->offset = temp->offset;
 	td->remainder = temp->len;
 	td->error = 0;
-	td->did_stall = 0;
+	td->did_stall = temp->did_stall;
 	td->short_pkt = temp->short_pkt;
 	td->alt_next = temp->setup_alt_next;
 }
@@ -782,6 +782,7 @@ atmegadci_setup_standard_chain(struct us
 	temp.td_next = xfer->td_start[0];
 	temp.offset = 0;
 	temp.setup_alt_next = xfer->flags_int.short_frames_ok;
+	temp.did_stall = !xfer->flags_int.control_stall;
 
 	sc = ATMEGA_BUS2SC(xfer->xroot->bus);
 	ep_no = (xfer->endpoint & UE_ADDR);

Modified: head/sys/dev/usb/controller/atmegadci.h
==============================================================================
--- head/sys/dev/usb/controller/atmegadci.h	Thu May 21 17:26:20 2009	(r192551)
+++ head/sys/dev/usb/controller/atmegadci.h	Thu May 21 17:39:21 2009	(r192552)
@@ -222,6 +222,7 @@ struct atmegadci_std_temp {
          * short_pkt = 1: transfer should not be short terminated
          */
 	uint8_t	setup_alt_next;
+	uint8_t did_stall;
 };
 
 struct atmegadci_config_desc {

Modified: head/sys/dev/usb/controller/musb_otg.c
==============================================================================
--- head/sys/dev/usb/controller/musb_otg.c	Thu May 21 17:26:20 2009	(r192551)
+++ head/sys/dev/usb/controller/musb_otg.c	Thu May 21 17:39:21 2009	(r192552)
@@ -1099,7 +1099,7 @@ musbotg_setup_standard_chain_sub(struct 
 	td->offset = temp->offset;
 	td->remainder = temp->len;
 	td->error = 0;
-	td->did_stall = 0;
+	td->did_stall = temp->did_stall;
 	td->short_pkt = temp->short_pkt;
 	td->alt_next = temp->setup_alt_next;
 }
@@ -1129,6 +1129,7 @@ musbotg_setup_standard_chain(struct usb2
 	temp.td_next = xfer->td_start[0];
 	temp.offset = 0;
 	temp.setup_alt_next = xfer->flags_int.short_frames_ok;
+	temp.did_stall = !xfer->flags_int.control_stall;
 
 	sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
 	ep_no = (xfer->endpoint & UE_ADDR);

Modified: head/sys/dev/usb/controller/musb_otg.h
==============================================================================
--- head/sys/dev/usb/controller/musb_otg.h	Thu May 21 17:26:20 2009	(r192551)
+++ head/sys/dev/usb/controller/musb_otg.h	Thu May 21 17:39:21 2009	(r192552)
@@ -332,6 +332,7 @@ struct musbotg_std_temp {
          * short_pkt = 1: transfer should not be short terminated
          */
 	uint8_t	setup_alt_next;
+	uint8_t did_stall;
 };
 
 struct musbotg_config_desc {

Modified: head/sys/dev/usb/controller/uss820dci.c
==============================================================================
--- head/sys/dev/usb/controller/uss820dci.c	Thu May 21 17:26:20 2009	(r192551)
+++ head/sys/dev/usb/controller/uss820dci.c	Thu May 21 17:39:21 2009	(r192552)
@@ -410,10 +410,10 @@ repeat:
 
 		/* read out EPCON register */
 		/* enable RX input */
-		if (!td->did_stall) {
+		if (!td->did_enable) {
 			uss820dci_update_shared_1(USS820_DCI_PC2SC(td->pc),
 			    USS820_EPCON, 0xFF, USS820_EPCON_RXIE);
-			td->did_stall = 1;
+			td->did_enable = 1;
 		}
 		return (1);		/* not complete */
 	}
@@ -573,10 +573,10 @@ repeat:
 	 * Enable TX output, which must happen after that we have written
 	 * data into the FIFO. This is undocumented.
 	 */
-	if (!td->did_stall) {
+	if (!td->did_enable) {
 		uss820dci_update_shared_1(USS820_DCI_PC2SC(td->pc),
 		    USS820_EPCON, 0xFF, USS820_EPCON_TXOE);
-		td->did_stall = 1;
+		td->did_enable = 1;
 	}
 	/* check remainder */
 	if (td->remainder == 0) {
@@ -813,7 +813,8 @@ uss820dci_setup_standard_chain_sub(struc
 	td->offset = temp->offset;
 	td->remainder = temp->len;
 	td->error = 0;
-	td->did_stall = 0;
+	td->did_enable = 0;
+	td->did_stall = temp->did_stall;
 	td->short_pkt = temp->short_pkt;
 	td->alt_next = temp->setup_alt_next;
 }
@@ -843,6 +844,7 @@ uss820dci_setup_standard_chain(struct us
 	temp.td_next = xfer->td_start[0];
 	temp.offset = 0;
 	temp.setup_alt_next = xfer->flags_int.short_frames_ok;
+	temp.did_stall = !xfer->flags_int.control_stall;
 
 	sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
 	ep_no = (xfer->endpoint & UE_ADDR);

Modified: head/sys/dev/usb/controller/uss820dci.h
==============================================================================
--- head/sys/dev/usb/controller/uss820dci.h	Thu May 21 17:26:20 2009	(r192551)
+++ head/sys/dev/usb/controller/uss820dci.h	Thu May 21 17:39:21 2009	(r192552)
@@ -280,6 +280,7 @@ struct uss820dci_td {
 	uint8_t	short_pkt:1;
 	uint8_t	support_multi_buffer:1;
 	uint8_t	did_stall:1;
+	uint8_t	did_enable:1;
 };
 
 struct uss820_std_temp {
@@ -296,6 +297,7 @@ struct uss820_std_temp {
          * short_pkt = 1: transfer should not be short terminated
          */
 	uint8_t	setup_alt_next;
+	uint8_t did_stall;
 };
 
 struct uss820dci_config_desc {

Modified: head/sys/dev/usb/usb_core.h
==============================================================================
--- head/sys/dev/usb/usb_core.h	Thu May 21 17:26:20 2009	(r192551)
+++ head/sys/dev/usb/usb_core.h	Thu May 21 17:39:21 2009	(r192552)
@@ -371,6 +371,7 @@ struct usb2_xfer_flags_int {
 	uint8_t	control_hdr:1;		/* set if control header should be
 					 * 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	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	Thu May 21 17:26:20 2009	(r192551)
+++ head/sys/dev/usb/usb_transfer.c	Thu May 21 17:39:21 2009	(r192552)
@@ -1225,9 +1225,13 @@ usb2_start_hardware_sub(struct usb2_xfer
 	usb2_frlength_t len;
 
 	/* Check for control endpoint stall */
-	if (xfer->flags.stall_pipe) {
-		/* no longer active */
+	if (xfer->flags.stall_pipe && xfer->flags_int.control_act) {
+		/* the control transfer is no longer active */
+		xfer->flags_int.control_stall = 1;
 		xfer->flags_int.control_act = 0;
+	} else {
+		/* don't stall control transfer by default */
+		xfer->flags_int.control_stall = 0;
 	}
 
 	/* Check for invalid number of frames */



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