From: Tony Lindgren Date: Wed, 21 Feb 2007 08:58:54 +0000 (-0800) Subject: musb_hdrc: Transfer remaining bytes with PIO X-Git-Tag: v2.6.21-omap1~10 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=b0a1bdcd58b6f4a9aaaf5be3e419e9fa60d015dd;p=linux-2.6-omap-h63xx.git musb_hdrc: Transfer remaining bytes with PIO DMA callback can manually transfer remaining 1 - 31 bytes after DMA transfer using PIO. This allows transferring a wider range of sizes with DMA. This needs to be tested with sync DMA transfers as PIO may not be mixed with sync DMA. Signed-off-by: Tony Lindgren --- diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c index 8e864d6c9a8..1d9d80f374c 100644 --- a/drivers/usb/musb/tusb6010_omap.c +++ b/drivers/usb/musb/tusb6010_omap.c @@ -146,7 +146,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data) struct musb_hw_ep *hw_ep = chdat->hw_ep; void __iomem *ep_conf = hw_ep->conf; void __iomem *musb_base = musb->pRegs; - unsigned long remaining, flags; + unsigned long remaining, flags, pio; int ch; spin_lock_irqsave(&musb->Lock, flags); @@ -170,21 +170,25 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data) remaining = TUSB_EP_CONFIG_XFR_SIZE(remaining); channel->dwActualLength = chdat->transfer_len - remaining; + pio = chdat->len - channel->dwActualLength; DBG(2, "DMA remaining %lu/%u\n", remaining, chdat->transfer_len); - /* Transfer remaining 1 - 31 bytes if DMA worked */ - if (remaining == 0) { - u32 pio; + /* Transfer remaining 1 - 31 bytes */ + if (pio > 0 && pio < 32) { u8 *buf; - pio = chdat->len - channel->dwActualLength; - buf = phys_to_virt((u32)chdat->dma_addr) - + chdat->transfer_len; - if (chdat->tx) + DBG(2, "Using PIO for remaining %i bytes\n", pio); + buf = phys_to_virt((u32)chdat->dma_addr) + chdat->transfer_len; + if (chdat->tx) { + consistent_sync(phys_to_virt((u32)chdat->dma_addr), + chdat->transfer_len, DMA_TO_DEVICE); musb_write_fifo(hw_ep, pio, buf); - else + } else { musb_read_fifo(hw_ep, pio, buf); + consistent_sync(phys_to_virt((u32)chdat->dma_addr), + chdat->transfer_len, DMA_FROM_DEVICE); + } channel->dwActualLength += pio; } @@ -201,7 +205,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data) if (!chdat->tx) musb_dma_completion(musb, chdat->epnum, chdat->tx); - /* We musb terminate short tx transfers manually by setting TXPKTRDY. + /* We must terminate short tx transfers manually by setting TXPKTRDY. * REVISIT: This same problem may occur with other MUSB dma as well. * Easy to test with g_ether by pinging the MUSB board with ping -s54. */ @@ -239,7 +243,7 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, s8 dmareq; s8 sync_dev; - if (unlikely(dma_addr & 0x1) || len < 32) + if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz)) return FALSE; chdat->transfer_len = len & ~0x1f;