One person working on a mass-storage driver (the usb protocol
side, not the block subsystem side) ran into a bug in how a
bit of net2280 dma automagic was handled.

This patch fixes it by calling existing dma chain patchup
code when the dma engine was forced to "hiccup" by having
a not-yet-valid entry in it.  The hiccup is needed in this
case since the IN data stage mustn't terminate with a
short transfer (zero length packet); but the status stage
is always a short packet.  The "terminate with short packet"
bit is endpoint state, not request state, so IN dma queues
sometimes need this kind of fixup.

Please merge.

- Dave
--- 1.28/drivers/usb/gadget/net2280.c   Sat Aug 23 19:04:48 2003
+++ edited/net2280.c    Thu Aug 28 08:26:28 2003
@@ -2431,6 +2431,28 @@
                        if ((tmp & (1 << DMA_SCATTER_GATHER_ENABLE)) == 0
                                        || (tmp & (1 << DMA_ENABLE)) == 0)
                                restart_dma (ep);
+#ifdef USE_DMA_CHAINING
+                       else if (ep->desc->bEndpointAddress & USB_DIR_IN) {
+                               struct net2280_request  *req;
+                               u32                     dmacount;
+
+                               /* the descriptor at the head of the chain
+                                * may still have VALID_BIT clear; that's
+                                * used to trigger changing DMA_FIFO_VALIDATE
+                                * (affects automagic zlp writes).
+                                */
+                               req = list_entry (ep->queue.next,
+                                               struct net2280_request, queue);
+                               dmacount = req->td->dmacount;
+                               dmacount &= __constant_cpu_to_le32 (
+                                               (1 << VALID_BIT)
+                                               | DMA_BYTE_COUNT_MASK);
+                               if (dmacount && (dmacount & valid_bit) == 0) {
+                                       stop_dma (ep->dma);
+                                       restart_dma (ep);
+                               }
+                       }
+#endif
                }
                ep->irqs++;
        }

Reply via email to