summaryrefslogtreecommitdiff
path: root/meta/packages/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/packages/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch')
-rw-r--r--meta/packages/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch417
1 files changed, 0 insertions, 417 deletions
diff --git a/meta/packages/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch b/meta/packages/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch
deleted file mode 100644
index 7d546e10b..000000000
--- a/meta/packages/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch
+++ /dev/null
@@ -1,417 +0,0 @@
-From 035cd4a26e9b1638b4b0419b98409026176563ca Mon Sep 17 00:00:00 2001
-From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
-Date: Thu, 26 Mar 2009 18:29:19 -0700
-Subject: [PATCH] musb: fix isochronous TXDMA (take 2)
-
-Multi-frame isochronous TX URBs transfers in DMA mode never
-complete with CPPI DMA because musb_host_tx() doesn't restart
-DMA on the second frame, only emitting a debug message.
-With Inventra DMA they complete, but in PIO mode. To fix:
-
- - Factor out programming of the DMA transfer from
- musb_ep_program() into musb_tx_dma_program();
-
- - Reorder the code at the end of musb_host_tx() to
- facilitate the fallback to PIO iff DMA fails;
-
- - Handle the buffer offset consistently for both
- PIO and DMA modes;
-
- - Add an argument to musb_ep_program() for the same
- reason (it only worked correctly with non-zero
- offset of the first frame in PIO mode);
-
- - Set the completed isochronous frame descriptor's
- 'actual_length' and 'status' fields correctly in
- DMA mode.
-
-Also, since CPPI reportedly doesn't like sending isochronous
-packets in the RNDIS mode, change the criterion for this
-mode to be used only for multi-packet transfers. (There's
-no need for that mode in the single-packet case anyway.)
-
-[ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: split comment paragraph
-into bullet list, shrink patch delta, style tweaks ]
-
-Signed-off-by: Pavel Kiryukhin <pkiryukhin-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
-Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
-Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
----
- drivers/usb/musb/cppi_dma.c | 1 +
- drivers/usb/musb/musb_host.c | 227 +++++++++++++++++++-----------------------
- 2 files changed, 105 insertions(+), 123 deletions(-)
-
-diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
-index 569ef0f..ac7227c 100644
---- a/drivers/usb/musb/cppi_dma.c
-+++ b/drivers/usb/musb/cppi_dma.c
-@@ -579,6 +579,7 @@ cppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx)
- * trigger the "send a ZLP?" confusion.
- */
- rndis = (maxpacket & 0x3f) == 0
-+ && length > maxpacket
- && length < 0xffff
- && (length % maxpacket) != 0;
-
-diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
-index 6591282..f6e84a0 100644
---- a/drivers/usb/musb/musb_host.c
-+++ b/drivers/usb/musb/musb_host.c
-@@ -96,8 +96,8 @@
-
-
- static void musb_ep_program(struct musb *musb, u8 epnum,
-- struct urb *urb, unsigned int nOut,
-- u8 *buf, u32 len);
-+ struct urb *urb, int is_out,
-+ u8 *buf, u32 offset, u32 len);
-
- /*
- * Clear TX fifo. Needed to avoid BABBLE errors.
-@@ -189,9 +189,10 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
- {
- u16 frame;
- u32 len;
-- void *buf;
- void __iomem *mbase = musb->mregs;
- struct urb *urb = next_urb(qh);
-+ void *buf = urb->transfer_buffer;
-+ u32 offset = 0;
- struct musb_hw_ep *hw_ep = qh->hw_ep;
- unsigned pipe = urb->pipe;
- u8 address = usb_pipedevice(pipe);
-@@ -214,7 +215,7 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
- case USB_ENDPOINT_XFER_ISOC:
- qh->iso_idx = 0;
- qh->frame = 0;
-- buf = urb->transfer_buffer + urb->iso_frame_desc[0].offset;
-+ offset = urb->iso_frame_desc[0].offset;
- len = urb->iso_frame_desc[0].length;
- break;
- default: /* bulk, interrupt */
-@@ -232,14 +233,14 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
- case USB_ENDPOINT_XFER_ISOC: s = "-iso"; break;
- default: s = "-intr"; break;
- }; s; }),
-- epnum, buf, len);
-+ epnum, buf + offset, len);
-
- /* Configure endpoint */
- if (is_in || hw_ep->is_shared_fifo)
- hw_ep->in_qh = qh;
- else
- hw_ep->out_qh = qh;
-- musb_ep_program(musb, epnum, urb, !is_in, buf, len);
-+ musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len);
-
- /* transmit may have more work: start it when it is time */
- if (is_in)
-@@ -250,7 +251,6 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
- case USB_ENDPOINT_XFER_ISOC:
- case USB_ENDPOINT_XFER_INT:
- DBG(3, "check whether there's still time for periodic Tx\n");
-- qh->iso_idx = 0;
- frame = musb_readw(mbase, MUSB_FRAME);
- /* FIXME this doesn't implement that scheduling policy ...
- * or handle framecounter wrapping
-@@ -631,14 +631,68 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep)
- ep->rx_reinit = 0;
- }
-
-+static bool musb_tx_dma_program(struct dma_controller *dma,
-+ struct musb_hw_ep *hw_ep, struct musb_qh *qh,
-+ struct urb *urb, u32 offset, u32 length)
-+{
-+ struct dma_channel *channel = hw_ep->tx_channel;
-+ void __iomem *epio = hw_ep->regs;
-+ u16 pkt_size = qh->maxpacket;
-+ u16 csr;
-+ u8 mode;
-+
-+#ifdef CONFIG_USB_INVENTRA_DMA
-+ if (length > channel->max_len)
-+ length = channel->max_len;
-+
-+ csr = musb_readw(epio, MUSB_TXCSR);
-+ if (length > pkt_size) {
-+ mode = 1;
-+ csr |= MUSB_TXCSR_AUTOSET
-+ | MUSB_TXCSR_DMAMODE
-+ | MUSB_TXCSR_DMAENAB;
-+ } else {
-+ mode = 0;
-+ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE);
-+ csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */
-+ }
-+ channel->desired_mode = mode;
-+ musb_writew(epio, MUSB_TXCSR, csr);
-+#else
-+ if (!is_cppi_enabled() && !tusb_dma_omap())
-+ return false;
-+
-+ channel->actual_len = 0;
-+
-+ /*
-+ * TX uses "RNDIS" mode automatically but needs help
-+ * to identify the zero-length-final-packet case.
-+ */
-+ mode = (urb->transfer_flags & URB_ZERO_PACKET) ? 1 : 0;
-+#endif
-+
-+ qh->segsize = length;
-+
-+ if (!dma->channel_program(channel, pkt_size, mode,
-+ urb->transfer_dma + offset, length)) {
-+ dma->channel_release(channel);
-+ hw_ep->tx_channel = NULL;
-+
-+ csr = musb_readw(epio, MUSB_TXCSR);
-+ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
-+ musb_writew(epio, MUSB_TXCSR, csr | MUSB_TXCSR_H_WZC_BITS);
-+ return false;
-+ }
-+ return true;
-+}
-
- /*
- * Program an HDRC endpoint as per the given URB
- * Context: irqs blocked, controller lock held
- */
- static void musb_ep_program(struct musb *musb, u8 epnum,
-- struct urb *urb, unsigned int is_out,
-- u8 *buf, u32 len)
-+ struct urb *urb, int is_out,
-+ u8 *buf, u32 offset, u32 len)
- {
- struct dma_controller *dma_controller;
- struct dma_channel *dma_channel;
-@@ -764,82 +818,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
- else
- load_count = min((u32) packet_sz, len);
-
--#ifdef CONFIG_USB_INVENTRA_DMA
-- if (dma_channel) {
-- qh->segsize = min(len, dma_channel->max_len);
-- if (qh->segsize <= packet_sz)
-- dma_channel->desired_mode = 0;
-- else
-- dma_channel->desired_mode = 1;
--
-- if (dma_channel->desired_mode == 0) {
-- /* Against the programming guide */
-- csr |= (MUSB_TXCSR_DMAENAB);
-- } else
-- csr |= (MUSB_TXCSR_AUTOSET
-- | MUSB_TXCSR_DMAENAB
-- | MUSB_TXCSR_DMAMODE);
-- musb_writew(epio, MUSB_TXCSR, csr);
--
-- dma_ok = dma_controller->channel_program(
-- dma_channel, packet_sz,
-- dma_channel->desired_mode,
-- urb->transfer_dma,
-- qh->segsize);
-- if (dma_ok) {
-- load_count = 0;
-- } else {
-- dma_controller->channel_release(dma_channel);
-- if (is_out)
-- hw_ep->tx_channel = NULL;
-- else
-- hw_ep->rx_channel = NULL;
-- dma_channel = NULL;
--
-- /*
-- * The programming guide says that we must
-- * clear the DMAENAB bit before DMAMODE...
-- */
-- csr = musb_readw(epio, MUSB_TXCSR);
-- csr &= ~(MUSB_TXCSR_DMAENAB
-- | MUSB_TXCSR_AUTOSET);
-- musb_writew(epio, MUSB_TXCSR, csr);
-- csr &= ~MUSB_TXCSR_DMAMODE;
-- musb_writew(epio, MUSB_TXCSR, csr);
-- }
-- }
--#endif
--
-- /* candidate for DMA */
-- if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) {
--
-- /* Defer enabling DMA */
-- dma_channel->actual_len = 0L;
-- qh->segsize = len;
--
-- /* TX uses "rndis" mode automatically, but needs help
-- * to identify the zero-length-final-packet case.
-- */
-- dma_ok = dma_controller->channel_program(
-- dma_channel, packet_sz,
-- (urb->transfer_flags
-- & URB_ZERO_PACKET)
-- == URB_ZERO_PACKET,
-- urb->transfer_dma,
-- qh->segsize);
-- if (dma_ok) {
-- load_count = 0;
-- } else {
-- dma_controller->channel_release(dma_channel);
-- hw_ep->tx_channel = NULL;
-- dma_channel = NULL;
--
-- /* REVISIT there's an error path here that
-- * needs handling: can't do dma, but
-- * there's no pio buffer address...
-- */
-- }
-- }
-+ if (dma_channel && musb_tx_dma_program(dma_controller,
-+ hw_ep, qh, urb, offset, len))
-+ load_count = 0;
-
- if (load_count) {
- /* PIO to load FIFO */
-@@ -899,7 +880,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
- dma_channel, packet_sz,
- !(urb->transfer_flags
- & URB_SHORT_NOT_OK),
-- urb->transfer_dma,
-+ urb->transfer_dma + offset,
- qh->segsize);
- if (!dma_ok) {
- dma_controller->channel_release(
-@@ -1142,8 +1123,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
- int pipe;
- bool done = false;
- u16 tx_csr;
-- size_t wLength = 0;
-- u8 *buf = NULL;
-+ size_t length = 0;
-+ size_t offset = 0;
- struct urb *urb;
- struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
- void __iomem *epio = hw_ep->regs;
-@@ -1161,7 +1142,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
- /* with CPPI, DMA sometimes triggers "extra" irqs */
- if (!urb) {
- DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
-- goto finish;
-+ return;
- }
-
- pipe = urb->pipe;
-@@ -1198,7 +1179,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
- musb_writew(epio, MUSB_TXCSR,
- MUSB_TXCSR_H_WZC_BITS
- | MUSB_TXCSR_TXPKTRDY);
-- goto finish;
-+ return;
- }
-
- if (status) {
-@@ -1230,29 +1211,28 @@ void musb_host_tx(struct musb *musb, u8 epnum)
- /* second cppi case */
- if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
- DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
-- goto finish;
--
-+ return;
- }
-
-- /* REVISIT this looks wrong... */
- if (!status || dma || usb_pipeisoc(pipe)) {
- if (dma)
-- wLength = dma->actual_len;
-+ length = dma->actual_len;
- else
-- wLength = qh->segsize;
-- qh->offset += wLength;
-+ length = qh->segsize;
-+ qh->offset += length;
-
- if (usb_pipeisoc(pipe)) {
- struct usb_iso_packet_descriptor *d;
-
- d = urb->iso_frame_desc + qh->iso_idx;
-- d->actual_length = qh->segsize;
-+ d->actual_length = length;
-+ d->status = status;
- if (++qh->iso_idx >= urb->number_of_packets) {
- done = true;
- } else {
- d++;
-- buf = urb->transfer_buffer + d->offset;
-- wLength = d->length;
-+ offset = d->offset;
-+ length = d->length;
- }
- } else if (dma) {
- done = true;
-@@ -1265,10 +1245,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
- & URB_ZERO_PACKET))
- done = true;
- if (!done) {
-- buf = urb->transfer_buffer
-- + qh->offset;
-- wLength = urb->transfer_buffer_length
-- - qh->offset;
-+ offset = qh->offset;
-+ length = urb->transfer_buffer_length - offset;
- }
- }
- }
-@@ -1287,28 +1265,31 @@ void musb_host_tx(struct musb *musb, u8 epnum)
- urb->status = status;
- urb->actual_length = qh->offset;
- musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT);
-+ return;
-+ } else if (usb_pipeisoc(pipe) && dma) {
-+ if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb,
-+ offset, length))
-+ return;
-+ } else if (tx_csr & MUSB_TXCSR_DMAENAB) {
-+ DBG(1, "not complete, but DMA enabled?\n");
-+ return;
-+ }
-
-- } else if (!(tx_csr & MUSB_TXCSR_DMAENAB)) {
-- /* WARN_ON(!buf); */
--
-- /* REVISIT: some docs say that when hw_ep->tx_double_buffered,
-- * (and presumably, fifo is not half-full) we should write TWO
-- * packets before updating TXCSR ... other docs disagree ...
-- */
-- /* PIO: start next packet in this URB */
-- if (wLength > qh->maxpacket)
-- wLength = qh->maxpacket;
-- musb_write_fifo(hw_ep, wLength, buf);
-- qh->segsize = wLength;
--
-- musb_ep_select(mbase, epnum);
-- musb_writew(epio, MUSB_TXCSR,
-- MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
-- } else
-- DBG(1, "not complete, but dma enabled?\n");
-+ /*
-+ * PIO: start next packet in this URB.
-+ *
-+ * REVISIT: some docs say that when hw_ep->tx_double_buffered,
-+ * (and presumably, FIFO is not half-full) we should write *two*
-+ * packets before updating TXCSR; other docs disagree...
-+ */
-+ if (length > qh->maxpacket)
-+ length = qh->maxpacket;
-+ musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset);
-+ qh->segsize = length;
-
--finish:
-- return;
-+ musb_ep_select(mbase, epnum);
-+ musb_writew(epio, MUSB_TXCSR,
-+ MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
- }
-
-
---
-1.6.0.4
-