svn commit: r190721 - head/sys/dev/usb/controller

Andrew Thompson thompsa at FreeBSD.org
Sun Apr 5 11:18:22 PDT 2009


Author: thompsa
Date: Sun Apr  5 18:18:16 2009
New Revision: 190721
URL: http://svn.freebsd.org/changeset/base/190721

Log:
  MFp4 //depot/projects/usb at 159673
  
  Fix a corner case around stalling SETUP packets in device side mode.
  
  Submitted by:	Hans Petter Selasky

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

Modified: head/sys/dev/usb/controller/at91dci.c
==============================================================================
--- head/sys/dev/usb/controller/at91dci.c	Sun Apr  5 18:18:07 2009	(r190720)
+++ head/sys/dev/usb/controller/at91dci.c	Sun Apr  5 18:18:16 2009	(r190721)
@@ -305,14 +305,11 @@ at91dci_setup_rx(struct at91dci_td *td)
 	    AT91_UDP_CSR_TXCOMP);
 
 	if (!(csr & AT91_UDP_CSR_RXSETUP)) {
-		/* abort any ongoing transfer */
-		if (!td->did_stall) {
-			DPRINTFN(5, "stalling\n");
-			temp |= AT91_UDP_CSR_FORCESTALL;
-			td->did_stall = 1;
-		}
 		goto not_complete;
 	}
+	/* clear did stall */
+	td->did_stall = 0;
+
 	/* get the packet byte count */
 	count = (csr & AT91_UDP_CSR_RXBYTECNT) >> 16;
 
@@ -362,6 +359,13 @@ at91dci_setup_rx(struct at91dci_td *td)
 	return (0);			/* complete */
 
 not_complete:
+	/* abort any ongoing transfer */
+	if (!td->did_stall) {
+		DPRINTFN(5, "stalling\n");
+		temp |= AT91_UDP_CSR_FORCESTALL;
+		td->did_stall = 1;
+	}
+
 	/* clear interrupts, if any */
 	if (temp) {
 		DPRINTFN(5, "clearing 0x%08x\n", temp);

Modified: head/sys/dev/usb/controller/atmegadci.c
==============================================================================
--- head/sys/dev/usb/controller/atmegadci.c	Sun Apr  5 18:18:07 2009	(r190720)
+++ head/sys/dev/usb/controller/atmegadci.c	Sun Apr  5 18:18:16 2009	(r190721)
@@ -250,16 +250,10 @@ atmegadci_setup_rx(struct atmegadci_td *
 	DPRINTFN(5, "UEINTX=0x%02x\n", temp);
 
 	if (!(temp & ATMEGA_UEINTX_RXSTPI)) {
-		/* abort any ongoing transfer */
-		if (!td->did_stall) {
-			DPRINTFN(5, "stalling\n");
-			ATMEGA_WRITE_1(sc, ATMEGA_UECONX,
-			    ATMEGA_UECONX_EPEN |
-			    ATMEGA_UECONX_STALLRQ);
-			td->did_stall = 1;
-		}
 		goto not_complete;
 	}
+	/* clear did stall */
+	td->did_stall = 0;
 	/* get the packet byte count */
 	count =
 	    (ATMEGA_READ_1(sc, ATMEGA_UEBCHX) << 8) |
@@ -304,6 +298,15 @@ atmegadci_setup_rx(struct atmegadci_td *
 	return (0);			/* complete */
 
 not_complete:
+	/* abort any ongoing transfer */
+	if (!td->did_stall) {
+		DPRINTFN(5, "stalling\n");
+		ATMEGA_WRITE_1(sc, ATMEGA_UECONX,
+		    ATMEGA_UECONX_EPEN |
+		    ATMEGA_UECONX_STALLRQ);
+		td->did_stall = 1;
+	}
+
 	/* we only want to know if there is a SETUP packet */
 	ATMEGA_WRITE_1(sc, ATMEGA_UEIENX, ATMEGA_UEIENX_RXSTPE);
 	return (1);			/* not complete */

Modified: head/sys/dev/usb/controller/musb_otg.c
==============================================================================
--- head/sys/dev/usb/controller/musb_otg.c	Sun Apr  5 18:18:07 2009	(r190720)
+++ head/sys/dev/usb/controller/musb_otg.c	Sun Apr  5 18:18:16 2009	(r190721)
@@ -255,6 +255,8 @@ musbotg_setup_rx(struct musbotg_td *td)
 	 * callback, hence the status stage is not complete.
 	 */
 	if (csr & MUSB2_MASK_CSR0L_DATAEND) {
+		/* do not stall at this point */
+		td->did_stall = 1;
 		/* wait for interrupt */
 		goto not_complete;
 	}
@@ -276,18 +278,13 @@ musbotg_setup_rx(struct musbotg_td *td)
 		sc->sc_ep0_busy = 0;
 	}
 	if (sc->sc_ep0_busy) {
-		/* abort any ongoing transfer */
-		if (!td->did_stall) {
-			DPRINTFN(4, "stalling\n");
-			MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
-			    MUSB2_MASK_CSR0L_SENDSTALL);
-			td->did_stall = 1;
-		}
 		goto not_complete;
 	}
 	if (!(csr & MUSB2_MASK_CSR0L_RXPKTRDY)) {
 		goto not_complete;
 	}
+	/* clear did stall flag */
+	td->did_stall = 0;
 	/* get the packet byte count */
 	count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
 
@@ -328,6 +325,13 @@ musbotg_setup_rx(struct musbotg_td *td)
 	return (0);			/* complete */
 
 not_complete:
+	/* abort any ongoing transfer */
+	if (!td->did_stall) {
+		DPRINTFN(4, "stalling\n");
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+		    MUSB2_MASK_CSR0L_SENDSTALL);
+		td->did_stall = 1;
+	}
 	return (1);			/* not complete */
 }
 

Modified: head/sys/dev/usb/controller/uss820dci.c
==============================================================================
--- head/sys/dev/usb/controller/uss820dci.c	Sun Apr  5 18:18:07 2009	(r190720)
+++ head/sys/dev/usb/controller/uss820dci.c	Sun Apr  5 18:18:16 2009	(r190721)
@@ -248,19 +248,11 @@ uss820dci_setup_rx(struct uss820dci_td *
 	DPRINTFN(5, "rx_stat=0x%02x rem=%u\n", rx_stat, td->remainder);
 
 	if (!(rx_stat & USS820_RXSTAT_RXSETUP)) {
-		/* abort any ongoing transfer */
-		if (!td->did_stall) {
-			DPRINTFN(5, "stalling\n");
-
-			/* set stall */
-
-			uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF,
-			    (USS820_EPCON_TXSTL | USS820_EPCON_RXSTL));
-
-			td->did_stall = 1;
-		}
 		goto not_complete;
 	}
+	/* clear did stall */
+	td->did_stall = 0;
+
 	/* clear stall and all I/O */
 	uss820dci_update_shared_1(sc, USS820_EPCON,
 	    0xFF ^ (USS820_EPCON_TXSTL |
@@ -332,6 +324,18 @@ uss820dci_setup_rx(struct uss820dci_td *
 	return (0);			/* complete */
 
 not_complete:
+	/* abort any ongoing transfer */
+	if (!td->did_stall) {
+		DPRINTFN(5, "stalling\n");
+
+		/* set stall */
+
+		uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF,
+		    (USS820_EPCON_TXSTL | USS820_EPCON_RXSTL));
+
+		td->did_stall = 1;
+	}
+
 	/* clear end overwrite flag, if any */
 	if (rx_stat & USS820_RXSTAT_RXSETUP) {
 		uss820dci_update_shared_1(sc, USS820_RXSTAT,


More information about the svn-src-head mailing list