summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch417
1 files changed, 417 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch
new file mode 100644
index 0000000000..7d546e10b0
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch
@@ -0,0 +1,417 @@
1From 035cd4a26e9b1638b4b0419b98409026176563ca Mon Sep 17 00:00:00 2001
2From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
3Date: Thu, 26 Mar 2009 18:29:19 -0700
4Subject: [PATCH] musb: fix isochronous TXDMA (take 2)
5
6Multi-frame isochronous TX URBs transfers in DMA mode never
7complete with CPPI DMA because musb_host_tx() doesn't restart
8DMA on the second frame, only emitting a debug message.
9With Inventra DMA they complete, but in PIO mode. To fix:
10
11 - Factor out programming of the DMA transfer from
12 musb_ep_program() into musb_tx_dma_program();
13
14 - Reorder the code at the end of musb_host_tx() to
15 facilitate the fallback to PIO iff DMA fails;
16
17 - Handle the buffer offset consistently for both
18 PIO and DMA modes;
19
20 - Add an argument to musb_ep_program() for the same
21 reason (it only worked correctly with non-zero
22 offset of the first frame in PIO mode);
23
24 - Set the completed isochronous frame descriptor's
25 'actual_length' and 'status' fields correctly in
26 DMA mode.
27
28Also, since CPPI reportedly doesn't like sending isochronous
29packets in the RNDIS mode, change the criterion for this
30mode to be used only for multi-packet transfers. (There's
31no need for that mode in the single-packet case anyway.)
32
33[ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: split comment paragraph
34into bullet list, shrink patch delta, style tweaks ]
35
36Signed-off-by: Pavel Kiryukhin <pkiryukhin-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
37Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org>
38Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
39---
40 drivers/usb/musb/cppi_dma.c | 1 +
41 drivers/usb/musb/musb_host.c | 227 +++++++++++++++++++-----------------------
42 2 files changed, 105 insertions(+), 123 deletions(-)
43
44diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
45index 569ef0f..ac7227c 100644
46--- a/drivers/usb/musb/cppi_dma.c
47+++ b/drivers/usb/musb/cppi_dma.c
48@@ -579,6 +579,7 @@ cppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx)
49 * trigger the "send a ZLP?" confusion.
50 */
51 rndis = (maxpacket & 0x3f) == 0
52+ && length > maxpacket
53 && length < 0xffff
54 && (length % maxpacket) != 0;
55
56diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
57index 6591282..f6e84a0 100644
58--- a/drivers/usb/musb/musb_host.c
59+++ b/drivers/usb/musb/musb_host.c
60@@ -96,8 +96,8 @@
61
62
63 static void musb_ep_program(struct musb *musb, u8 epnum,
64- struct urb *urb, unsigned int nOut,
65- u8 *buf, u32 len);
66+ struct urb *urb, int is_out,
67+ u8 *buf, u32 offset, u32 len);
68
69 /*
70 * Clear TX fifo. Needed to avoid BABBLE errors.
71@@ -189,9 +189,10 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
72 {
73 u16 frame;
74 u32 len;
75- void *buf;
76 void __iomem *mbase = musb->mregs;
77 struct urb *urb = next_urb(qh);
78+ void *buf = urb->transfer_buffer;
79+ u32 offset = 0;
80 struct musb_hw_ep *hw_ep = qh->hw_ep;
81 unsigned pipe = urb->pipe;
82 u8 address = usb_pipedevice(pipe);
83@@ -214,7 +215,7 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
84 case USB_ENDPOINT_XFER_ISOC:
85 qh->iso_idx = 0;
86 qh->frame = 0;
87- buf = urb->transfer_buffer + urb->iso_frame_desc[0].offset;
88+ offset = urb->iso_frame_desc[0].offset;
89 len = urb->iso_frame_desc[0].length;
90 break;
91 default: /* bulk, interrupt */
92@@ -232,14 +233,14 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
93 case USB_ENDPOINT_XFER_ISOC: s = "-iso"; break;
94 default: s = "-intr"; break;
95 }; s; }),
96- epnum, buf, len);
97+ epnum, buf + offset, len);
98
99 /* Configure endpoint */
100 if (is_in || hw_ep->is_shared_fifo)
101 hw_ep->in_qh = qh;
102 else
103 hw_ep->out_qh = qh;
104- musb_ep_program(musb, epnum, urb, !is_in, buf, len);
105+ musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len);
106
107 /* transmit may have more work: start it when it is time */
108 if (is_in)
109@@ -250,7 +251,6 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
110 case USB_ENDPOINT_XFER_ISOC:
111 case USB_ENDPOINT_XFER_INT:
112 DBG(3, "check whether there's still time for periodic Tx\n");
113- qh->iso_idx = 0;
114 frame = musb_readw(mbase, MUSB_FRAME);
115 /* FIXME this doesn't implement that scheduling policy ...
116 * or handle framecounter wrapping
117@@ -631,14 +631,68 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep)
118 ep->rx_reinit = 0;
119 }
120
121+static bool musb_tx_dma_program(struct dma_controller *dma,
122+ struct musb_hw_ep *hw_ep, struct musb_qh *qh,
123+ struct urb *urb, u32 offset, u32 length)
124+{
125+ struct dma_channel *channel = hw_ep->tx_channel;
126+ void __iomem *epio = hw_ep->regs;
127+ u16 pkt_size = qh->maxpacket;
128+ u16 csr;
129+ u8 mode;
130+
131+#ifdef CONFIG_USB_INVENTRA_DMA
132+ if (length > channel->max_len)
133+ length = channel->max_len;
134+
135+ csr = musb_readw(epio, MUSB_TXCSR);
136+ if (length > pkt_size) {
137+ mode = 1;
138+ csr |= MUSB_TXCSR_AUTOSET
139+ | MUSB_TXCSR_DMAMODE
140+ | MUSB_TXCSR_DMAENAB;
141+ } else {
142+ mode = 0;
143+ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE);
144+ csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */
145+ }
146+ channel->desired_mode = mode;
147+ musb_writew(epio, MUSB_TXCSR, csr);
148+#else
149+ if (!is_cppi_enabled() && !tusb_dma_omap())
150+ return false;
151+
152+ channel->actual_len = 0;
153+
154+ /*
155+ * TX uses "RNDIS" mode automatically but needs help
156+ * to identify the zero-length-final-packet case.
157+ */
158+ mode = (urb->transfer_flags & URB_ZERO_PACKET) ? 1 : 0;
159+#endif
160+
161+ qh->segsize = length;
162+
163+ if (!dma->channel_program(channel, pkt_size, mode,
164+ urb->transfer_dma + offset, length)) {
165+ dma->channel_release(channel);
166+ hw_ep->tx_channel = NULL;
167+
168+ csr = musb_readw(epio, MUSB_TXCSR);
169+ csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
170+ musb_writew(epio, MUSB_TXCSR, csr | MUSB_TXCSR_H_WZC_BITS);
171+ return false;
172+ }
173+ return true;
174+}
175
176 /*
177 * Program an HDRC endpoint as per the given URB
178 * Context: irqs blocked, controller lock held
179 */
180 static void musb_ep_program(struct musb *musb, u8 epnum,
181- struct urb *urb, unsigned int is_out,
182- u8 *buf, u32 len)
183+ struct urb *urb, int is_out,
184+ u8 *buf, u32 offset, u32 len)
185 {
186 struct dma_controller *dma_controller;
187 struct dma_channel *dma_channel;
188@@ -764,82 +818,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
189 else
190 load_count = min((u32) packet_sz, len);
191
192-#ifdef CONFIG_USB_INVENTRA_DMA
193- if (dma_channel) {
194- qh->segsize = min(len, dma_channel->max_len);
195- if (qh->segsize <= packet_sz)
196- dma_channel->desired_mode = 0;
197- else
198- dma_channel->desired_mode = 1;
199-
200- if (dma_channel->desired_mode == 0) {
201- /* Against the programming guide */
202- csr |= (MUSB_TXCSR_DMAENAB);
203- } else
204- csr |= (MUSB_TXCSR_AUTOSET
205- | MUSB_TXCSR_DMAENAB
206- | MUSB_TXCSR_DMAMODE);
207- musb_writew(epio, MUSB_TXCSR, csr);
208-
209- dma_ok = dma_controller->channel_program(
210- dma_channel, packet_sz,
211- dma_channel->desired_mode,
212- urb->transfer_dma,
213- qh->segsize);
214- if (dma_ok) {
215- load_count = 0;
216- } else {
217- dma_controller->channel_release(dma_channel);
218- if (is_out)
219- hw_ep->tx_channel = NULL;
220- else
221- hw_ep->rx_channel = NULL;
222- dma_channel = NULL;
223-
224- /*
225- * The programming guide says that we must
226- * clear the DMAENAB bit before DMAMODE...
227- */
228- csr = musb_readw(epio, MUSB_TXCSR);
229- csr &= ~(MUSB_TXCSR_DMAENAB
230- | MUSB_TXCSR_AUTOSET);
231- musb_writew(epio, MUSB_TXCSR, csr);
232- csr &= ~MUSB_TXCSR_DMAMODE;
233- musb_writew(epio, MUSB_TXCSR, csr);
234- }
235- }
236-#endif
237-
238- /* candidate for DMA */
239- if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) {
240-
241- /* Defer enabling DMA */
242- dma_channel->actual_len = 0L;
243- qh->segsize = len;
244-
245- /* TX uses "rndis" mode automatically, but needs help
246- * to identify the zero-length-final-packet case.
247- */
248- dma_ok = dma_controller->channel_program(
249- dma_channel, packet_sz,
250- (urb->transfer_flags
251- & URB_ZERO_PACKET)
252- == URB_ZERO_PACKET,
253- urb->transfer_dma,
254- qh->segsize);
255- if (dma_ok) {
256- load_count = 0;
257- } else {
258- dma_controller->channel_release(dma_channel);
259- hw_ep->tx_channel = NULL;
260- dma_channel = NULL;
261-
262- /* REVISIT there's an error path here that
263- * needs handling: can't do dma, but
264- * there's no pio buffer address...
265- */
266- }
267- }
268+ if (dma_channel && musb_tx_dma_program(dma_controller,
269+ hw_ep, qh, urb, offset, len))
270+ load_count = 0;
271
272 if (load_count) {
273 /* PIO to load FIFO */
274@@ -899,7 +880,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
275 dma_channel, packet_sz,
276 !(urb->transfer_flags
277 & URB_SHORT_NOT_OK),
278- urb->transfer_dma,
279+ urb->transfer_dma + offset,
280 qh->segsize);
281 if (!dma_ok) {
282 dma_controller->channel_release(
283@@ -1142,8 +1123,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
284 int pipe;
285 bool done = false;
286 u16 tx_csr;
287- size_t wLength = 0;
288- u8 *buf = NULL;
289+ size_t length = 0;
290+ size_t offset = 0;
291 struct urb *urb;
292 struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
293 void __iomem *epio = hw_ep->regs;
294@@ -1161,7 +1142,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
295 /* with CPPI, DMA sometimes triggers "extra" irqs */
296 if (!urb) {
297 DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
298- goto finish;
299+ return;
300 }
301
302 pipe = urb->pipe;
303@@ -1198,7 +1179,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
304 musb_writew(epio, MUSB_TXCSR,
305 MUSB_TXCSR_H_WZC_BITS
306 | MUSB_TXCSR_TXPKTRDY);
307- goto finish;
308+ return;
309 }
310
311 if (status) {
312@@ -1230,29 +1211,28 @@ void musb_host_tx(struct musb *musb, u8 epnum)
313 /* second cppi case */
314 if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
315 DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
316- goto finish;
317-
318+ return;
319 }
320
321- /* REVISIT this looks wrong... */
322 if (!status || dma || usb_pipeisoc(pipe)) {
323 if (dma)
324- wLength = dma->actual_len;
325+ length = dma->actual_len;
326 else
327- wLength = qh->segsize;
328- qh->offset += wLength;
329+ length = qh->segsize;
330+ qh->offset += length;
331
332 if (usb_pipeisoc(pipe)) {
333 struct usb_iso_packet_descriptor *d;
334
335 d = urb->iso_frame_desc + qh->iso_idx;
336- d->actual_length = qh->segsize;
337+ d->actual_length = length;
338+ d->status = status;
339 if (++qh->iso_idx >= urb->number_of_packets) {
340 done = true;
341 } else {
342 d++;
343- buf = urb->transfer_buffer + d->offset;
344- wLength = d->length;
345+ offset = d->offset;
346+ length = d->length;
347 }
348 } else if (dma) {
349 done = true;
350@@ -1265,10 +1245,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
351 & URB_ZERO_PACKET))
352 done = true;
353 if (!done) {
354- buf = urb->transfer_buffer
355- + qh->offset;
356- wLength = urb->transfer_buffer_length
357- - qh->offset;
358+ offset = qh->offset;
359+ length = urb->transfer_buffer_length - offset;
360 }
361 }
362 }
363@@ -1287,28 +1265,31 @@ void musb_host_tx(struct musb *musb, u8 epnum)
364 urb->status = status;
365 urb->actual_length = qh->offset;
366 musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT);
367+ return;
368+ } else if (usb_pipeisoc(pipe) && dma) {
369+ if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb,
370+ offset, length))
371+ return;
372+ } else if (tx_csr & MUSB_TXCSR_DMAENAB) {
373+ DBG(1, "not complete, but DMA enabled?\n");
374+ return;
375+ }
376
377- } else if (!(tx_csr & MUSB_TXCSR_DMAENAB)) {
378- /* WARN_ON(!buf); */
379-
380- /* REVISIT: some docs say that when hw_ep->tx_double_buffered,
381- * (and presumably, fifo is not half-full) we should write TWO
382- * packets before updating TXCSR ... other docs disagree ...
383- */
384- /* PIO: start next packet in this URB */
385- if (wLength > qh->maxpacket)
386- wLength = qh->maxpacket;
387- musb_write_fifo(hw_ep, wLength, buf);
388- qh->segsize = wLength;
389-
390- musb_ep_select(mbase, epnum);
391- musb_writew(epio, MUSB_TXCSR,
392- MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
393- } else
394- DBG(1, "not complete, but dma enabled?\n");
395+ /*
396+ * PIO: start next packet in this URB.
397+ *
398+ * REVISIT: some docs say that when hw_ep->tx_double_buffered,
399+ * (and presumably, FIFO is not half-full) we should write *two*
400+ * packets before updating TXCSR; other docs disagree...
401+ */
402+ if (length > qh->maxpacket)
403+ length = qh->maxpacket;
404+ musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset);
405+ qh->segsize = length;
406
407-finish:
408- return;
409+ musb_ep_select(mbase, epnum);
410+ musb_writew(epio, MUSB_TXCSR,
411+ MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
412 }
413
414
415--
4161.6.0.4
417