aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/musb_host.c
diff options
context:
space:
mode:
authorSergei Shtylyov <sshtylyov@ru.mvista.com>2009-03-26 21:29:19 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-04-17 13:50:26 -0400
commit6b6e97107f12f3a9f7b5b43a6c3b94409240bcff (patch)
tree2ae05da51a4020bf4892c9b2b307583813ffc9a9 /drivers/usb/musb/musb_host.c
parentb6e434a5404b9ce8c285ea081b6ea5c523b29db4 (diff)
USB: 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@users.sourceforge.net: split comment paragraph into bullet list, shrink patch delta, style tweaks ] Signed-off-by: Pavel Kiryukhin <pkiryukhin@ru.mvista.com> Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/musb/musb_host.c')
-rw-r--r--drivers/usb/musb/musb_host.c227
1 files changed, 104 insertions, 123 deletions
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 1dfaaa6acfaf..db1b57415ec7 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -97,8 +97,8 @@
97 97
98 98
99static void musb_ep_program(struct musb *musb, u8 epnum, 99static void musb_ep_program(struct musb *musb, u8 epnum,
100 struct urb *urb, unsigned int nOut, 100 struct urb *urb, int is_out,
101 u8 *buf, u32 len); 101 u8 *buf, u32 offset, u32 len);
102 102
103/* 103/*
104 * Clear TX fifo. Needed to avoid BABBLE errors. 104 * Clear TX fifo. Needed to avoid BABBLE errors.
@@ -192,9 +192,10 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
192{ 192{
193 u16 frame; 193 u16 frame;
194 u32 len; 194 u32 len;
195 void *buf;
196 void __iomem *mbase = musb->mregs; 195 void __iomem *mbase = musb->mregs;
197 struct urb *urb = next_urb(qh); 196 struct urb *urb = next_urb(qh);
197 void *buf = urb->transfer_buffer;
198 u32 offset = 0;
198 struct musb_hw_ep *hw_ep = qh->hw_ep; 199 struct musb_hw_ep *hw_ep = qh->hw_ep;
199 unsigned pipe = urb->pipe; 200 unsigned pipe = urb->pipe;
200 u8 address = usb_pipedevice(pipe); 201 u8 address = usb_pipedevice(pipe);
@@ -217,7 +218,7 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
217 case USB_ENDPOINT_XFER_ISOC: 218 case USB_ENDPOINT_XFER_ISOC:
218 qh->iso_idx = 0; 219 qh->iso_idx = 0;
219 qh->frame = 0; 220 qh->frame = 0;
220 buf = urb->transfer_buffer + urb->iso_frame_desc[0].offset; 221 offset = urb->iso_frame_desc[0].offset;
221 len = urb->iso_frame_desc[0].length; 222 len = urb->iso_frame_desc[0].length;
222 break; 223 break;
223 default: /* bulk, interrupt */ 224 default: /* bulk, interrupt */
@@ -235,14 +236,14 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
235 case USB_ENDPOINT_XFER_ISOC: s = "-iso"; break; 236 case USB_ENDPOINT_XFER_ISOC: s = "-iso"; break;
236 default: s = "-intr"; break; 237 default: s = "-intr"; break;
237 }; s; }), 238 }; s; }),
238 epnum, buf, len); 239 epnum, buf + offset, len);
239 240
240 /* Configure endpoint */ 241 /* Configure endpoint */
241 if (is_in || hw_ep->is_shared_fifo) 242 if (is_in || hw_ep->is_shared_fifo)
242 hw_ep->in_qh = qh; 243 hw_ep->in_qh = qh;
243 else 244 else
244 hw_ep->out_qh = qh; 245 hw_ep->out_qh = qh;
245 musb_ep_program(musb, epnum, urb, !is_in, buf, len); 246 musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len);
246 247
247 /* transmit may have more work: start it when it is time */ 248 /* transmit may have more work: start it when it is time */
248 if (is_in) 249 if (is_in)
@@ -253,7 +254,6 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
253 case USB_ENDPOINT_XFER_ISOC: 254 case USB_ENDPOINT_XFER_ISOC:
254 case USB_ENDPOINT_XFER_INT: 255 case USB_ENDPOINT_XFER_INT:
255 DBG(3, "check whether there's still time for periodic Tx\n"); 256 DBG(3, "check whether there's still time for periodic Tx\n");
256 qh->iso_idx = 0;
257 frame = musb_readw(mbase, MUSB_FRAME); 257 frame = musb_readw(mbase, MUSB_FRAME);
258 /* FIXME this doesn't implement that scheduling policy ... 258 /* FIXME this doesn't implement that scheduling policy ...
259 * or handle framecounter wrapping 259 * or handle framecounter wrapping
@@ -634,14 +634,68 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep)
634 ep->rx_reinit = 0; 634 ep->rx_reinit = 0;
635} 635}
636 636
637static bool musb_tx_dma_program(struct dma_controller *dma,
638 struct musb_hw_ep *hw_ep, struct musb_qh *qh,
639 struct urb *urb, u32 offset, u32 length)
640{
641 struct dma_channel *channel = hw_ep->tx_channel;
642 void __iomem *epio = hw_ep->regs;
643 u16 pkt_size = qh->maxpacket;
644 u16 csr;
645 u8 mode;
646
647#ifdef CONFIG_USB_INVENTRA_DMA
648 if (length > channel->max_len)
649 length = channel->max_len;
650
651 csr = musb_readw(epio, MUSB_TXCSR);
652 if (length > pkt_size) {
653 mode = 1;
654 csr |= MUSB_TXCSR_AUTOSET
655 | MUSB_TXCSR_DMAMODE
656 | MUSB_TXCSR_DMAENAB;
657 } else {
658 mode = 0;
659 csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE);
660 csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */
661 }
662 channel->desired_mode = mode;
663 musb_writew(epio, MUSB_TXCSR, csr);
664#else
665 if (!is_cppi_enabled() && !tusb_dma_omap())
666 return false;
667
668 channel->actual_len = 0;
669
670 /*
671 * TX uses "RNDIS" mode automatically but needs help
672 * to identify the zero-length-final-packet case.
673 */
674 mode = (urb->transfer_flags & URB_ZERO_PACKET) ? 1 : 0;
675#endif
676
677 qh->segsize = length;
678
679 if (!dma->channel_program(channel, pkt_size, mode,
680 urb->transfer_dma + offset, length)) {
681 dma->channel_release(channel);
682 hw_ep->tx_channel = NULL;
683
684 csr = musb_readw(epio, MUSB_TXCSR);
685 csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB);
686 musb_writew(epio, MUSB_TXCSR, csr | MUSB_TXCSR_H_WZC_BITS);
687 return false;
688 }
689 return true;
690}
637 691
638/* 692/*
639 * Program an HDRC endpoint as per the given URB 693 * Program an HDRC endpoint as per the given URB
640 * Context: irqs blocked, controller lock held 694 * Context: irqs blocked, controller lock held
641 */ 695 */
642static void musb_ep_program(struct musb *musb, u8 epnum, 696static void musb_ep_program(struct musb *musb, u8 epnum,
643 struct urb *urb, unsigned int is_out, 697 struct urb *urb, int is_out,
644 u8 *buf, u32 len) 698 u8 *buf, u32 offset, u32 len)
645{ 699{
646 struct dma_controller *dma_controller; 700 struct dma_controller *dma_controller;
647 struct dma_channel *dma_channel; 701 struct dma_channel *dma_channel;
@@ -768,82 +822,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
768 else 822 else
769 load_count = min((u32) packet_sz, len); 823 load_count = min((u32) packet_sz, len);
770 824
771#ifdef CONFIG_USB_INVENTRA_DMA 825 if (dma_channel && musb_tx_dma_program(dma_controller,
772 if (dma_channel) { 826 hw_ep, qh, urb, offset, len))
773 qh->segsize = min(len, dma_channel->max_len); 827 load_count = 0;
774 if (qh->segsize <= packet_sz)
775 dma_channel->desired_mode = 0;
776 else
777 dma_channel->desired_mode = 1;
778
779 if (dma_channel->desired_mode == 0) {
780 /* Against the programming guide */
781 csr |= (MUSB_TXCSR_DMAENAB);
782 } else
783 csr |= (MUSB_TXCSR_AUTOSET
784 | MUSB_TXCSR_DMAENAB
785 | MUSB_TXCSR_DMAMODE);
786 musb_writew(epio, MUSB_TXCSR, csr);
787
788 dma_ok = dma_controller->channel_program(
789 dma_channel, packet_sz,
790 dma_channel->desired_mode,
791 urb->transfer_dma,
792 qh->segsize);
793 if (dma_ok) {
794 load_count = 0;
795 } else {
796 dma_controller->channel_release(dma_channel);
797 if (is_out)
798 hw_ep->tx_channel = NULL;
799 else
800 hw_ep->rx_channel = NULL;
801 dma_channel = NULL;
802
803 /*
804 * The programming guide says that we must
805 * clear the DMAENAB bit before DMAMODE...
806 */
807 csr = musb_readw(epio, MUSB_TXCSR);
808 csr &= ~(MUSB_TXCSR_DMAENAB
809 | MUSB_TXCSR_AUTOSET);
810 musb_writew(epio, MUSB_TXCSR, csr);
811 csr &= ~MUSB_TXCSR_DMAMODE;
812 musb_writew(epio, MUSB_TXCSR, csr);
813 }
814 }
815#endif
816
817 /* candidate for DMA */
818 if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) {
819
820 /* Defer enabling DMA */
821 dma_channel->actual_len = 0L;
822 qh->segsize = len;
823
824 /* TX uses "rndis" mode automatically, but needs help
825 * to identify the zero-length-final-packet case.
826 */
827 dma_ok = dma_controller->channel_program(
828 dma_channel, packet_sz,
829 (urb->transfer_flags
830 & URB_ZERO_PACKET)
831 == URB_ZERO_PACKET,
832 urb->transfer_dma,
833 qh->segsize);
834 if (dma_ok) {
835 load_count = 0;
836 } else {
837 dma_controller->channel_release(dma_channel);
838 hw_ep->tx_channel = NULL;
839 dma_channel = NULL;
840
841 /* REVISIT there's an error path here that
842 * needs handling: can't do dma, but
843 * there's no pio buffer address...
844 */
845 }
846 }
847 828
848 if (load_count) { 829 if (load_count) {
849 /* PIO to load FIFO */ 830 /* PIO to load FIFO */
@@ -903,7 +884,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
903 dma_channel, packet_sz, 884 dma_channel, packet_sz,
904 !(urb->transfer_flags 885 !(urb->transfer_flags
905 & URB_SHORT_NOT_OK), 886 & URB_SHORT_NOT_OK),
906 urb->transfer_dma, 887 urb->transfer_dma + offset,
907 qh->segsize); 888 qh->segsize);
908 if (!dma_ok) { 889 if (!dma_ok) {
909 dma_controller->channel_release( 890 dma_controller->channel_release(
@@ -1146,8 +1127,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
1146 int pipe; 1127 int pipe;
1147 bool done = false; 1128 bool done = false;
1148 u16 tx_csr; 1129 u16 tx_csr;
1149 size_t wLength = 0; 1130 size_t length = 0;
1150 u8 *buf = NULL; 1131 size_t offset = 0;
1151 struct urb *urb; 1132 struct urb *urb;
1152 struct musb_hw_ep *hw_ep = musb->endpoints + epnum; 1133 struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
1153 void __iomem *epio = hw_ep->regs; 1134 void __iomem *epio = hw_ep->regs;
@@ -1165,7 +1146,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
1165 /* with CPPI, DMA sometimes triggers "extra" irqs */ 1146 /* with CPPI, DMA sometimes triggers "extra" irqs */
1166 if (!urb) { 1147 if (!urb) {
1167 DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr); 1148 DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
1168 goto finish; 1149 return;
1169 } 1150 }
1170 1151
1171 pipe = urb->pipe; 1152 pipe = urb->pipe;
@@ -1202,7 +1183,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
1202 musb_writew(epio, MUSB_TXCSR, 1183 musb_writew(epio, MUSB_TXCSR,
1203 MUSB_TXCSR_H_WZC_BITS 1184 MUSB_TXCSR_H_WZC_BITS
1204 | MUSB_TXCSR_TXPKTRDY); 1185 | MUSB_TXCSR_TXPKTRDY);
1205 goto finish; 1186 return;
1206 } 1187 }
1207 1188
1208 if (status) { 1189 if (status) {
@@ -1234,8 +1215,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
1234 /* second cppi case */ 1215 /* second cppi case */
1235 if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { 1216 if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
1236 DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr); 1217 DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr);
1237 goto finish; 1218 return;
1238
1239 } 1219 }
1240 1220
1241 if (is_dma_capable() && dma && !status) { 1221 if (is_dma_capable() && dma && !status) {
@@ -1299,25 +1279,25 @@ void musb_host_tx(struct musb *musb, u8 epnum)
1299 } 1279 }
1300 } 1280 }
1301 1281
1302 /* REVISIT this looks wrong... */
1303 if (!status || dma || usb_pipeisoc(pipe)) { 1282 if (!status || dma || usb_pipeisoc(pipe)) {
1304 if (dma) 1283 if (dma)
1305 wLength = dma->actual_len; 1284 length = dma->actual_len;
1306 else 1285 else
1307 wLength = qh->segsize; 1286 length = qh->segsize;
1308 qh->offset += wLength; 1287 qh->offset += length;
1309 1288
1310 if (usb_pipeisoc(pipe)) { 1289 if (usb_pipeisoc(pipe)) {
1311 struct usb_iso_packet_descriptor *d; 1290 struct usb_iso_packet_descriptor *d;
1312 1291
1313 d = urb->iso_frame_desc + qh->iso_idx; 1292 d = urb->iso_frame_desc + qh->iso_idx;
1314 d->actual_length = qh->segsize; 1293 d->actual_length = length;
1294 d->status = status;
1315 if (++qh->iso_idx >= urb->number_of_packets) { 1295 if (++qh->iso_idx >= urb->number_of_packets) {
1316 done = true; 1296 done = true;
1317 } else { 1297 } else {
1318 d++; 1298 d++;
1319 buf = urb->transfer_buffer + d->offset; 1299 offset = d->offset;
1320 wLength = d->length; 1300 length = d->length;
1321 } 1301 }
1322 } else if (dma) { 1302 } else if (dma) {
1323 done = true; 1303 done = true;
@@ -1330,10 +1310,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
1330 & URB_ZERO_PACKET)) 1310 & URB_ZERO_PACKET))
1331 done = true; 1311 done = true;
1332 if (!done) { 1312 if (!done) {
1333 buf = urb->transfer_buffer 1313 offset = qh->offset;
1334 + qh->offset; 1314 length = urb->transfer_buffer_length - offset;
1335 wLength = urb->transfer_buffer_length
1336 - qh->offset;
1337 } 1315 }
1338 } 1316 }
1339 } 1317 }
@@ -1352,28 +1330,31 @@ void musb_host_tx(struct musb *musb, u8 epnum)
1352 urb->status = status; 1330 urb->status = status;
1353 urb->actual_length = qh->offset; 1331 urb->actual_length = qh->offset;
1354 musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT); 1332 musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT);
1333 return;
1334 } else if (usb_pipeisoc(pipe) && dma) {
1335 if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb,
1336 offset, length))
1337 return;
1338 } else if (tx_csr & MUSB_TXCSR_DMAENAB) {
1339 DBG(1, "not complete, but DMA enabled?\n");
1340 return;
1341 }
1355 1342
1356 } else if (!(tx_csr & MUSB_TXCSR_DMAENAB)) { 1343 /*
1357 /* WARN_ON(!buf); */ 1344 * PIO: start next packet in this URB.
1358 1345 *
1359 /* REVISIT: some docs say that when hw_ep->tx_double_buffered, 1346 * REVISIT: some docs say that when hw_ep->tx_double_buffered,
1360 * (and presumably, fifo is not half-full) we should write TWO 1347 * (and presumably, FIFO is not half-full) we should write *two*
1361 * packets before updating TXCSR ... other docs disagree ... 1348 * packets before updating TXCSR; other docs disagree...
1362 */ 1349 */
1363 /* PIO: start next packet in this URB */ 1350 if (length > qh->maxpacket)
1364 if (wLength > qh->maxpacket) 1351 length = qh->maxpacket;
1365 wLength = qh->maxpacket; 1352 musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset);
1366 musb_write_fifo(hw_ep, wLength, buf); 1353 qh->segsize = length;
1367 qh->segsize = wLength;
1368
1369 musb_ep_select(mbase, epnum);
1370 musb_writew(epio, MUSB_TXCSR,
1371 MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
1372 } else
1373 DBG(1, "not complete, but dma enabled?\n");
1374 1354
1375finish: 1355 musb_ep_select(mbase, epnum);
1376 return; 1356 musb_writew(epio, MUSB_TXCSR,
1357 MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY);
1377} 1358}
1378 1359
1379 1360