On Friday 21 January 2005 1:21 am, Vladimir Trukhin wrote: > > So the following conditions are always FALSE in this context. Seems like > the hardware (UDCCS registers specifically) doesn't give us the correct > status info. > > ----------- taken from pxa2xx_udc.c:pxa2xx_ep_set_halt() ----------- > ... > 1081 if ((ep->bEndpointAddress & USB_DIR_IN) != 0 > 1082 && ((*ep->reg_udccs & UDCCS_BI_TFS) == 0 > 1083 || !list_empty(&ep->queue))) { > 1084 local_irq_restore(flags); > 1085 return -EAGAIN; > 1086 } > ... > --------------------------------------------------------------------------------------- >
Hmm, does the following patch help at all? Presumably it compiles! It's kind of dirty; the real fix should probably be to not return the request from the queue until its ZLP gets ACKed. And it may well break with DMA (but nobody's using that lately). - Dave
--- 1.32/drivers/usb/gadget/pxa2xx_udc.c 2004-10-15 15:39:36 -07:00 +++ edited/drivers/usb/gadget/pxa2xx_udc.c 2005-01-21 09:45:16 -08:00 @@ -104,6 +104,11 @@ #include "pxa2xx_udc.h" +/* FIXME Make IN-DMA work, saving CPU time. It worked in some tests, for + * always-aligned network packets; but it also failed in some cases. + * (OUT-DMA is only partly implemented.) + */ + #ifdef USE_DMA static int use_dma = 1; module_param(use_dma, bool, 0); @@ -449,6 +454,7 @@ int is_last, is_short; count = write_packet(ep->reg_uddr, req, max); + ep->ackwait = 1; /* last packet is usually short (or a zlp) */ if (unlikely (count != max)) @@ -1078,6 +1084,7 @@ local_irq_save(flags); if ((ep->bEndpointAddress & USB_DIR_IN) != 0 + && ep->ackwait && ((*ep->reg_udccs & UDCCS_BI_TFS) == 0 || !list_empty(&ep->queue))) { local_irq_restore(flags); @@ -1958,6 +1965,7 @@ tmp &= udccs; if (likely (tmp)) *ep->reg_udccs = tmp; + ep->ackwait = 0; if (req && likely ((udccs & UDCCS_BI_TFS) != 0)) completed = write_fifo(ep, req); --- 1.19/drivers/usb/gadget/pxa2xx_udc.h 2004-02-10 10:32:22 -08:00 +++ edited/drivers/usb/gadget/pxa2xx_udc.h 2005-01-21 09:34:04 -08:00 @@ -60,6 +60,7 @@ unsigned stopped : 1; unsigned dma_fixup : 1; + unsigned ackwait : 1; /* UDCCS = UDC Control/Status for this EP * UBCR = UDC Byte Count Remaining (contents of OUT fifo)