aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb
diff options
context:
space:
mode:
authorAjay Kumar Gupta <ajay.gupta@ti.com>2008-10-29 09:10:31 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-11-13 17:45:00 -0500
commitf82a689faeb328ba7c194782f42cc438519d508e (patch)
tree82f8847b5162267e05e89edc01d0633d8c550def /drivers/usb/musb
parent352d026338378b1f13f044e33c1047da6e470056 (diff)
usb: musb: Fix for isochronous IN transfer
Fixes blurred capture images in dma mode. Isochronous error field in urb and source data buffer pointer were not updated properly in dma mode. Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com> Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r--drivers/usb/musb/musb_host.c77
1 files changed, 57 insertions, 20 deletions
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 3133990f04ec..981d49738ec5 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -1507,10 +1507,29 @@ void musb_host_rx(struct musb *musb, u8 epnum)
1507 musb_writew(hw_ep->regs, MUSB_RXCSR, val); 1507 musb_writew(hw_ep->regs, MUSB_RXCSR, val);
1508 1508
1509#ifdef CONFIG_USB_INVENTRA_DMA 1509#ifdef CONFIG_USB_INVENTRA_DMA
1510 if (usb_pipeisoc(pipe)) {
1511 struct usb_iso_packet_descriptor *d;
1512
1513 d = urb->iso_frame_desc + qh->iso_idx;
1514 d->actual_length = xfer_len;
1515
1516 /* even if there was an error, we did the dma
1517 * for iso_frame_desc->length
1518 */
1519 if (d->status != EILSEQ && d->status != -EOVERFLOW)
1520 d->status = 0;
1521
1522 if (++qh->iso_idx >= urb->number_of_packets)
1523 done = true;
1524 else
1525 done = false;
1526
1527 } else {
1510 /* done if urb buffer is full or short packet is recd */ 1528 /* done if urb buffer is full or short packet is recd */
1511 done = (urb->actual_length + xfer_len >= 1529 done = (urb->actual_length + xfer_len >=
1512 urb->transfer_buffer_length 1530 urb->transfer_buffer_length
1513 || dma->actual_len < qh->maxpacket); 1531 || dma->actual_len < qh->maxpacket);
1532 }
1514 1533
1515 /* send IN token for next packet, without AUTOREQ */ 1534 /* send IN token for next packet, without AUTOREQ */
1516 if (!done) { 1535 if (!done) {
@@ -1547,7 +1566,8 @@ void musb_host_rx(struct musb *musb, u8 epnum)
1547 if (dma) { 1566 if (dma) {
1548 struct dma_controller *c; 1567 struct dma_controller *c;
1549 u16 rx_count; 1568 u16 rx_count;
1550 int ret; 1569 int ret, length;
1570 dma_addr_t buf;
1551 1571
1552 rx_count = musb_readw(epio, MUSB_RXCOUNT); 1572 rx_count = musb_readw(epio, MUSB_RXCOUNT);
1553 1573
@@ -1560,6 +1580,35 @@ void musb_host_rx(struct musb *musb, u8 epnum)
1560 1580
1561 c = musb->dma_controller; 1581 c = musb->dma_controller;
1562 1582
1583 if (usb_pipeisoc(pipe)) {
1584 int status = 0;
1585 struct usb_iso_packet_descriptor *d;
1586
1587 d = urb->iso_frame_desc + qh->iso_idx;
1588
1589 if (iso_err) {
1590 status = -EILSEQ;
1591 urb->error_count++;
1592 }
1593 if (rx_count > d->length) {
1594 if (status == 0) {
1595 status = -EOVERFLOW;
1596 urb->error_count++;
1597 }
1598 DBG(2, "** OVERFLOW %d into %d\n",\
1599 rx_count, d->length);
1600
1601 length = d->length;
1602 } else
1603 length = rx_count;
1604 d->status = status;
1605 buf = urb->transfer_dma + d->offset;
1606 } else {
1607 length = rx_count;
1608 buf = urb->transfer_dma +
1609 urb->actual_length;
1610 }
1611
1563 dma->desired_mode = 0; 1612 dma->desired_mode = 0;
1564#ifdef USE_MODE1 1613#ifdef USE_MODE1
1565 /* because of the issue below, mode 1 will 1614 /* because of the issue below, mode 1 will
@@ -1571,6 +1620,12 @@ void musb_host_rx(struct musb *musb, u8 epnum)
1571 urb->actual_length) 1620 urb->actual_length)
1572 > qh->maxpacket) 1621 > qh->maxpacket)
1573 dma->desired_mode = 1; 1622 dma->desired_mode = 1;
1623 if (rx_count < hw_ep->max_packet_sz_rx) {
1624 length = rx_count;
1625 dma->bDesiredMode = 0;
1626 } else {
1627 length = urb->transfer_buffer_length;
1628 }
1574#endif 1629#endif
1575 1630
1576/* Disadvantage of using mode 1: 1631/* Disadvantage of using mode 1:
@@ -1608,12 +1663,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)
1608 */ 1663 */
1609 ret = c->channel_program( 1664 ret = c->channel_program(
1610 dma, qh->maxpacket, 1665 dma, qh->maxpacket,
1611 dma->desired_mode, 1666 dma->desired_mode, buf, length);
1612 urb->transfer_dma
1613 + urb->actual_length,
1614 (dma->desired_mode == 0)
1615 ? rx_count
1616 : urb->transfer_buffer_length);
1617 1667
1618 if (!ret) { 1668 if (!ret) {
1619 c->channel_release(dma); 1669 c->channel_release(dma);
@@ -1631,19 +1681,6 @@ void musb_host_rx(struct musb *musb, u8 epnum)
1631 } 1681 }
1632 } 1682 }
1633 1683
1634 if (dma && usb_pipeisoc(pipe)) {
1635 struct usb_iso_packet_descriptor *d;
1636 int iso_stat = status;
1637
1638 d = urb->iso_frame_desc + qh->iso_idx;
1639 d->actual_length += xfer_len;
1640 if (iso_err) {
1641 iso_stat = -EILSEQ;
1642 urb->error_count++;
1643 }
1644 d->status = iso_stat;
1645 }
1646
1647finish: 1684finish:
1648 urb->actual_length += xfer_len; 1685 urb->actual_length += xfer_len;
1649 qh->offset += xfer_len; 1686 qh->offset += xfer_len;