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;
 };
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to