RE: [PATCH 2/2] USB: musb: gadget: fix MUSB_TXMAXP and MUSB_RXMAXP configuration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



-----Original Message-----
From: Ming Lei [mailto:tom.leiming@xxxxxxxxx]
Sent: Wednesday, October 20, 2010 12:00 AM
To: Liu, Bob
Cc: Bob Liu; balbi@xxxxxx; Cai, Cliff; Zhang, Sonic; greg@xxxxxxxxx; linux-usb@xxxxxxxxxxxxxxx; David Brownell; Gadiyar, Anand; Mike Frysinger; Sergei Shtylyov
Subject: Re: [PATCH 2/2] USB: musb: gadget: fix MUSB_TXMAXP and MUSB_RXMAXP configuration

Hi Bob,

2010/10/19 Liu, Bob <Bob.Liu@xxxxxxxxxx>:

> Hi, Ming
>
> Sorry for my mistake, in my test the failed case was case5 not case4.
> Case5 is BULK OUT transfer, so this patch changed txstate() only won't have effect,
> sorry for the noise.
>
> Now the problem is if "fixed MUSB_TXMAXP and MUSB_RXMAXP configuration",
> double buffer mode will be auto enabled on our platform which makes case5 fail sometimes.
>
> And the root cause is in function rxstate()
> ===
> if (csr & MUSB_RXCSR_RXPKTRDY) {
>        len = musb_readw(epio, MUSB_RXCOUNT);
> ==
> len will be read out with very strange value like 1022,514 which are not expected and
> make things mess, so case5 failed.

I guess it is caused by double buffer, since double buffer support depends
on rx_double_buffered flag now but the flag isn't set in blackfin musb.

Please try the patch below. If the patch still doesn't work, please enable musb
debug switch and post the debug info on list.

diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 2a82362..f86dce9 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -536,6 +536,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,
@@ -574,6 +593,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 9cfd18b..bcecd13 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -920,6 +927,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);

@@ -956,6 +965,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);
======================================================================
Hi,

I made a new clean environment to test it yesterday.
The test results is different. Now testusb#5 and #7 will always Broken pipe
Like this:
root@adam-desktop:~/usb# ./testusb -D /proc/bus/usb/002/020 -c 1024 -t 5 -s 32768 -g 8
unknown speed   /proc/bus/usb/002/020
/proc/bus/usb/002/020 test 1 --> 32 (Broken pipe)

And on the board:
root:/> PHY: 0:01 - Link is Up - 100/Full
zero gadget: high speed config #3: source/sink
zero gadget: bad OUT byte, buf[3072] = 85, pattern 0

And the all the change in my environment is(diff from the version worked fine):
===
--- musb_gadget.c       (revision 9256)
+++ musb_gadget.c       (working copy)
@@ -313,7 +313,7 @@
                         * currently, don't use mode1 on Blackfin.
                         */
 #if !defined(CONFIG_BLACKFIN) || defined(USE_MODE1)
-                       request_size = min_t(size_t, request->length,
+                       request_size = min_t(size_t, request->length - request->actual,
                                                musb_ep->dma->max_len);
 #else
                        request_size = fifo_count;
@@ -512,29 +512,16 @@
                                                | MUSB_TXCSR_TXPKTRDY);
                                request->zero = 0;
                        }
-                       if (request->actual < request->length)
-                               return;
+                       if (request->actual == request->length) {
+                               /* ... or if not, then complete it. */
+                               musb_g_giveback(musb_ep, request, 0);

-                       /* ... or if not, then complete it. */
-                       musb_g_giveback(musb_ep, request, 0);
-
-                       /*
-                        * Kickstart next transfer if appropriate;
-                        * the packet that just completed might not
-                        * be transmitted for hours or days.
-                        * REVISIT for double buffering...
-                        * FIXME revisit for stalls too...
-                        */
-                       musb_ep_select(mbase, epnum);
-                       csr = musb_readw(epio, MUSB_TXCSR);
-                       if (csr & MUSB_TXCSR_FIFONOTEMPTY)
-                               return;
-
-                       request = musb_ep->desc ? next_request(musb_ep) : NULL;
-                       if (!request) {
-                               DBG(4, "%s idle now\n",
-                                       musb_ep->end_point.name);
-                               return;
+                               request = musb_ep->desc ? next_request(musb_ep) : NULL;
+                               if (!request) {
+                                       DBG(4, "%s idle now\n",
+                                                       musb_ep->end_point.name);
+                                       return;
+                               }
                        }
                }

@@ -672,15 +659,18 @@
                                musb_writew(epio, MUSB_RXCSR,
                                        csr | MUSB_RXCSR_DMAMODE);
 #endif
+                               if(musb_ep->hw_ep->rx_double_buffered) /* bf enabled double buffer mode but not set rx_double_buffered */
+                                       csr |= MUSB_RXCSR_AUTOCLEAR;
                                musb_writew(epio, MUSB_RXCSR, csr);

                                if (request->actual < request->length) {
                                        int transfer_size = 0;
 #ifdef USE_MODE1
-                                       transfer_size = min(request->length,
+                                       transfer_size = min(request->length - request->actual,
                                                        channel->max_len);
 #else
-                                       transfer_size = len;
+                                       transfer_size = min(request->length - request->actual,
+                                                       len);
 #endif
                                        if (transfer_size <= musb_ep->packet_sz)
                                                musb_ep->dma->desired_mode = 0;
@@ -819,7 +809,7 @@

 #if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA)
                /* Autoclear doesn't clear RxPktRdy for short packets */
-               if ((dma->desired_mode == 0)
+               if ((dma->desired_mode == 0 && !hw_ep->rx_double_buffered)
                                || (dma->actual_len
                                        & (musb_ep->packet_sz - 1))) {
                        /* ack the read! */
@@ -830,8 +820,14 @@
                /* incomplete, and not short? wait for next IN packet */
                if ((request->actual < request->length)
                                && (musb_ep->dma->actual_len
-                                       == musb_ep->packet_sz))
+                                       == musb_ep->packet_sz)) {
+                       if(hw_ep->rx_double_buffered) {
+                               csr = musb_readw(epio, MUSB_RXCSR);
+                               if(csr & MUSB_RXCSR_RXPKTRDY)
+                                       goto received;
+                       }
                        return;
+               }
 #endif
                musb_g_giveback(musb_ep, request, 0);

@@ -839,7 +835,7 @@
                if (!request)
                        return;
        }
-
+received:
        /* analyze request if the ep is hot */
        if (request)
                rxstate(musb, to_musb_request(request));
@@ -918,9 +914,9 @@
                 * to disable double buffering mode. Currently, It seems that double
                 * buffering has problem if musb RTL revision number < 2.0.
                 */
-               if (musb->hwvers < MUSB_HWVERS_2000)
-                       musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx);
-               else
+               //if (musb->hwvers < MUSB_HWVERS_2000)
+               //      musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx);
+               //else
                        musb_writew(regs, MUSB_TXMAXP, tmp);

                csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG;
@@ -944,7 +940,10 @@
                        goto fail;
                if (tmp > hw_ep->max_packet_sz_rx)
                        goto fail;
-
+               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;
+               }
                int_rxe |= (1 << epnum);
                musb_writew(mbase, MUSB_INTRRXE, int_rxe);

@@ -954,9 +953,9 @@
                /* Set RXMAXP with the FIFO size of the endpoint
                 * to disable double buffering mode.
                 */
-               if (musb->hwvers < MUSB_HWVERS_2000)
-                       musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_rx);
-               else
+               //if (musb->hwvers < MUSB_HWVERS_2000)
+               //      musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_rx);
+               //else
                        musb_writew(regs, MUSB_RXMAXP, tmp);

                /* force shared fifo to OUT-only mode */
===

Is there any patch I forgot to patch in order to make double buffer mode works well?

Thanks
--
-Bob
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux