ChangeSet 1.1276.1.58, 2003/08/28 10:53:17-07:00, david-b@pacbell.net

[PATCH] USB: net2280, patch dma chains

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.


 drivers/usb/gadget/net2280.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+)


diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
--- a/drivers/usb/gadget/net2280.c	Tue Sep  2 12:42:59 2003
+++ b/drivers/usb/gadget/net2280.c	Tue Sep  2 12:42:59 2003
@@ -2432,6 +2432,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++;
 	}
