Hi Bob, 2010/11/10 Bob Liu <lliubbo@xxxxxxxxx>: > Our spec said when double buffering enabled > " > Set up an ISR, sensitive to the SOF_B interrupt, that reads the > FIFO_FULL_R bit, reads the USB_RXCOUNT status register, and finally > removes one or two packets (equaling from the USB_RXCOUNT number > of bytes) from the FIFO and clears RXPKTRDY. > > Set SOF_B=1 in USB_INTRUSBE to generate an interrupt on each start > of frame. > " Suppose you meet data corruption issue in test #5, so it is bulk transfer, and should not be related with SOF in principle. > > We didn't see g_ether problem on our platform without this patch, it works fine. > Could you give detail step how to reproduce the g_ether problem? Did you test g_ether and g_zero(test #6) at full speed? I don't think the tests at fullspeed can be OK without my patch. > > After added this patch, double buffer will always auto enabled on our > platform which will cause > problem as our spec said on double buffer mode it use SOF_B interrupt > and FIFO_FULL_R bit etc. In fact, double buffer implementation inside chip should not be very difficult and seems there should not be bugs here, so I guess musb IP doesn't provide double buffer switch to disable the feature. Could you apply the attachment patch against linus tree plus musb patches submitted by Felipe to feedback the log when the data corruption is triggered by test #5? I remembered the similar problem touched me before, but was fixed by my previous double buffer patches. Maybe bfin musb IP is newer version, and something is not considered by previous patches. The patch only adds some debug messages to dump csr against the last patch sent to Bob. Good luck thanks, -- Lei Ming
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 69797e5..a70523d 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -537,6 +537,25 @@ static inline void musb_configure_ep0(struct musb *musb) musb->endpoints[0].is_shared_fifo = true; } +static inline void musb_update_double_fifo(struct musb_ep *musb_ep, + int rx) +{ + struct musb_hw_ep *hw_ep = musb_ep->hw_ep; + + if (rx) { + if (hw_ep->max_packet_sz_rx >= (musb_ep->packet_sz * 2)) { + hw_ep->rx_double_buffered = 1; + hw_ep->max_packet_sz_rx >>= 1; + } else + hw_ep->rx_double_buffered = 0; + } else { + if (hw_ep->max_packet_sz_tx >= (musb_ep->packet_sz * 2)) { + hw_ep->tx_double_buffered = 1; + hw_ep->max_packet_sz_tx >>= 1; + } else + hw_ep->tx_double_buffered = 0; + } +} #else static inline int musb_read_fifosize(struct musb *musb, @@ -575,6 +594,11 @@ static inline void musb_configure_ep0(struct musb *musb) musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE; musb->endpoints[0].is_shared_fifo = true; } +static inline void musb_update_double_fifo(struct musb_ep *musb_ep, + int rx) +{ + +} #endif /* CONFIG_BLACKFIN */ diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index e98b3f4..c9fdf2c 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -657,6 +657,11 @@ static void rxstate(struct musb *musb, struct musb_request *req) if (csr & MUSB_RXCSR_RXPKTRDY) { len = musb_readw(epio, MUSB_RXCOUNT); + if (len != 512 && len != 1024) { + printk("%s:%d csr=%x rx_double_buffer=%d\n", + __func__, __LINE__, csr, + hw_ep->rx_double_buffered); + } if (request->actual < request->length) { #ifdef CONFIG_USB_INVENTRA_DMA if (is_dma_capable() && musb_ep->dma) { @@ -979,6 +984,8 @@ static int musb_gadget_enable(struct usb_ep *ep, goto fail; } + musb_update_double_fifo(musb_ep, 0); + int_txe |= (1 << epnum); musb_writew(mbase, MUSB_INTRTXE, int_txe); @@ -1015,6 +1022,8 @@ static int musb_gadget_enable(struct usb_ep *ep, goto fail; } + musb_update_double_fifo(musb_ep, 1); + int_rxe |= (1 << epnum); musb_writew(mbase, MUSB_INTRRXE, int_rxe);