Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Sep 2012 18:59:20 +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: r240969 - head/sys/dev/usb/controller
Message-ID:  <201209261859.q8QIxKRq076677@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Wed Sep 26 18:59:20 2012
New Revision: 240969
URL: http://svn.freebsd.org/changeset/base/240969

Log:
  Make sure the DWC OTG host mode channels are given enough time to disable.

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

Modified: head/sys/dev/usb/controller/dwc_otg.c
==============================================================================
--- head/sys/dev/usb/controller/dwc_otg.c	Wed Sep 26 18:11:43 2012	(r240968)
+++ head/sys/dev/usb/controller/dwc_otg.c	Wed Sep 26 18:59:20 2012	(r240969)
@@ -507,6 +507,7 @@ static uint8_t
 dwc_otg_host_channel_wait(struct dwc_otg_td *td)
 {
 	struct dwc_otg_softc *sc;
+	uint16_t frame;
 	uint8_t x;
 
 	x = td->channel;
@@ -524,6 +525,8 @@ dwc_otg_host_channel_wait(struct dwc_otg
 	if (x == 0)
 		return (0);	/* wait */
 
+	frame = DWC_OTG_READ_4(sc, DOTG_HFNUM) & HFNUM_FRNUM_MASK;
+
 	/* find new disabled channel */
 	for (x = 1; x != sc->sc_host_ch_max; x++) {
 
@@ -539,6 +542,9 @@ dwc_otg_host_channel_wait(struct dwc_otg
 			continue;
 		}
 
+		if (sc->sc_chan_state[x].last_frame == frame)
+			continue;
+
 		sc->sc_chan_state[td->channel].allocated = 0;
 		sc->sc_chan_state[x].allocated = 1;
 
@@ -577,6 +583,7 @@ static uint8_t
 dwc_otg_host_channel_alloc(struct dwc_otg_td *td)
 {
 	struct dwc_otg_softc *sc;
+	uint16_t frame;
 	uint8_t x;
 	uint8_t max_channel;
 
@@ -594,6 +601,8 @@ dwc_otg_host_channel_alloc(struct dwc_ot
 		x = 1;
 	}
 
+	frame = DWC_OTG_READ_4(sc, DOTG_HFNUM) & HFNUM_FRNUM_MASK;
+
 	for (; x != max_channel; x++) {
 
 		uint32_t hcchar;
@@ -608,6 +617,9 @@ dwc_otg_host_channel_alloc(struct dwc_ot
 			continue;
 		}
 
+		if (sc->sc_chan_state[x].last_frame == frame)
+			continue;
+
 		sc->sc_chan_state[x].allocated = 1;
 
 		/* clear interrupts */
@@ -633,8 +645,12 @@ dwc_otg_host_channel_disable(struct dwc_
 {
 	uint32_t hcchar;
 	hcchar = DWC_OTG_READ_4(sc, DOTG_HCCHAR(x));
-	if (hcchar & (HCCHAR_CHENA | HCCHAR_CHDIS))
+	if (hcchar & (HCCHAR_CHENA | HCCHAR_CHDIS)) {
+		/* don't re-use channel until next SOF is transmitted */
+		sc->sc_chan_state[x].last_frame =
+		    DWC_OTG_READ_4(sc, DOTG_HFNUM) & HFNUM_FRNUM_MASK;
 		DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(x), HCCHAR_CHENA | HCCHAR_CHDIS);
+	}
 }
 
 static void

Modified: head/sys/dev/usb/controller/dwc_otg.h
==============================================================================
--- head/sys/dev/usb/controller/dwc_otg.h	Wed Sep 26 18:11:43 2012	(r240968)
+++ head/sys/dev/usb/controller/dwc_otg.h	Wed Sep 26 18:59:20 2012	(r240969)
@@ -140,6 +140,7 @@ struct dwc_otg_profile {
 
 struct dwc_otg_chan_state {
 	uint32_t hcint;
+	uint16_t last_frame;
 	uint8_t allocated;
 	uint8_t suspended;
 };



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