614683faf8
SVN-Revision: 13613
62 lines
2.3 KiB
Diff
62 lines
2.3 KiB
Diff
From d8310bb7e4ee4a9f3433a9a1e0e87567337299cb Mon Sep 17 00:00:00 2001
|
|
From: mokopatches <mokopatches@openmoko.org>
|
|
Date: Fri, 4 Apr 2008 11:33:55 +0100
|
|
Subject: [PATCH] s3c2410_udc-2440_dual_packet-workaround.patch
|
|
This is a patch that seems to make the USB hangs on the S3C2440 go away. At
|
|
least a good amount of ping torture didn't make them come back so far.
|
|
|
|
The issue is that, if there are several back-to-back packets,
|
|
sometimes no interrupt is generated for one of them. This
|
|
seems to be caused by the mysterious dual packet mode, which
|
|
the USB hardware enters automatically if the endpoint size is
|
|
half that of the FIFO. (On the 2440, this is the normal
|
|
situation for bulk data endpoints.)
|
|
|
|
There is also a timing factor in this. I think what happens is
|
|
that the USB hardware automatically sends an acknowledgement
|
|
if there is only one packet in the FIFO (the FIFO has space
|
|
for two). If another packet arrives before the host has
|
|
retrieved and acknowledged the previous one, no interrupt is
|
|
generated for that second one.
|
|
|
|
However, there may be an indication. There is one undocumented
|
|
bit (none of the 244x manuals document it), OUT_CRS1_REG[1],
|
|
that seems to be set suspiciously often when this condition
|
|
occurs. There is also CLR_DATA_TOGGLE, OUT_CRS1_REG[7], which
|
|
may have a function related to this. (The Samsung manual is
|
|
rather terse on that, as usual.)
|
|
|
|
This needs to be examined further. For now, the patch seems to do the
|
|
trick.
|
|
|
|
Note that this is not a clean solution by any means, because we
|
|
might potentially get stuck in that interrupt for quite a while.
|
|
---
|
|
drivers/usb/gadget/s3c2410_udc.c | 3 +++
|
|
1 files changed, 3 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
|
|
index 4ce050c..d4a17af 100644
|
|
--- a/drivers/usb/gadget/s3c2410_udc.c
|
|
+++ b/drivers/usb/gadget/s3c2410_udc.c
|
|
@@ -845,6 +845,7 @@ static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
|
|
u32 ep_csr1;
|
|
u32 idx;
|
|
|
|
+handle_ep_again:
|
|
if (likely (!list_empty(&ep->queue)))
|
|
req = list_entry(ep->queue.next,
|
|
struct s3c2410_request, queue);
|
|
@@ -884,6 +885,8 @@ static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
|
|
|
|
if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) {
|
|
s3c2410_udc_read_fifo(ep,req);
|
|
+ if (s3c2410_udc_fifo_count_out())
|
|
+ goto handle_ep_again;
|
|
}
|
|
}
|
|
}
|
|
--
|
|
1.5.6.5
|
|
|