diff options
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 58 |
1 files changed, 42 insertions, 16 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index dce305bd62a5..1c771045ccaa 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -1565,6 +1565,16 @@ itd_link_urb ( | |||
1565 | 1565 | ||
1566 | #define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR) | 1566 | #define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR) |
1567 | 1567 | ||
1568 | /* Process and recycle a completed ITD. Return true iff its urb completed, | ||
1569 | * and hence its completion callback probably added things to the hardware | ||
1570 | * schedule. | ||
1571 | * | ||
1572 | * Note that we carefully avoid recycling this descriptor until after any | ||
1573 | * completion callback runs, so that it won't be reused quickly. That is, | ||
1574 | * assuming (a) no more than two urbs per frame on this endpoint, and also | ||
1575 | * (b) only this endpoint's completions submit URBs. It seems some silicon | ||
1576 | * corrupts things if you reuse completed descriptors very quickly... | ||
1577 | */ | ||
1568 | static unsigned | 1578 | static unsigned |
1569 | itd_complete ( | 1579 | itd_complete ( |
1570 | struct ehci_hcd *ehci, | 1580 | struct ehci_hcd *ehci, |
@@ -1577,6 +1587,7 @@ itd_complete ( | |||
1577 | int urb_index = -1; | 1587 | int urb_index = -1; |
1578 | struct ehci_iso_stream *stream = itd->stream; | 1588 | struct ehci_iso_stream *stream = itd->stream; |
1579 | struct usb_device *dev; | 1589 | struct usb_device *dev; |
1590 | unsigned retval = false; | ||
1580 | 1591 | ||
1581 | /* for each uframe with a packet */ | 1592 | /* for each uframe with a packet */ |
1582 | for (uframe = 0; uframe < 8; uframe++) { | 1593 | for (uframe = 0; uframe < 8; uframe++) { |
@@ -1610,15 +1621,9 @@ itd_complete ( | |||
1610 | } | 1621 | } |
1611 | } | 1622 | } |
1612 | 1623 | ||
1613 | usb_put_urb (urb); | ||
1614 | itd->urb = NULL; | ||
1615 | itd->stream = NULL; | ||
1616 | list_move (&itd->itd_list, &stream->free_list); | ||
1617 | iso_stream_put (ehci, stream); | ||
1618 | |||
1619 | /* handle completion now? */ | 1624 | /* handle completion now? */ |
1620 | if (likely ((urb_index + 1) != urb->number_of_packets)) | 1625 | if (likely ((urb_index + 1) != urb->number_of_packets)) |
1621 | return 0; | 1626 | goto done; |
1622 | 1627 | ||
1623 | /* ASSERT: it's really the last itd for this urb | 1628 | /* ASSERT: it's really the last itd for this urb |
1624 | list_for_each_entry (itd, &stream->td_list, itd_list) | 1629 | list_for_each_entry (itd, &stream->td_list, itd_list) |
@@ -1628,6 +1633,7 @@ itd_complete ( | |||
1628 | /* give urb back to the driver ... can be out-of-order */ | 1633 | /* give urb back to the driver ... can be out-of-order */ |
1629 | dev = urb->dev; | 1634 | dev = urb->dev; |
1630 | ehci_urb_done(ehci, urb, 0); | 1635 | ehci_urb_done(ehci, urb, 0); |
1636 | retval = true; | ||
1631 | urb = NULL; | 1637 | urb = NULL; |
1632 | 1638 | ||
1633 | /* defer stopping schedule; completion can submit */ | 1639 | /* defer stopping schedule; completion can submit */ |
@@ -1645,8 +1651,15 @@ itd_complete ( | |||
1645 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); | 1651 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); |
1646 | } | 1652 | } |
1647 | iso_stream_put (ehci, stream); | 1653 | iso_stream_put (ehci, stream); |
1654 | /* OK to recycle this ITD now that its completion callback ran. */ | ||
1655 | done: | ||
1656 | usb_put_urb(urb); | ||
1657 | itd->urb = NULL; | ||
1658 | itd->stream = NULL; | ||
1659 | list_move(&itd->itd_list, &stream->free_list); | ||
1660 | iso_stream_put(ehci, stream); | ||
1648 | 1661 | ||
1649 | return 1; | 1662 | return retval; |
1650 | } | 1663 | } |
1651 | 1664 | ||
1652 | /*-------------------------------------------------------------------------*/ | 1665 | /*-------------------------------------------------------------------------*/ |
@@ -1950,6 +1963,16 @@ sitd_link_urb ( | |||
1950 | #define SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \ | 1963 | #define SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \ |
1951 | | SITD_STS_XACT | SITD_STS_MMF) | 1964 | | SITD_STS_XACT | SITD_STS_MMF) |
1952 | 1965 | ||
1966 | /* Process and recycle a completed SITD. Return true iff its urb completed, | ||
1967 | * and hence its completion callback probably added things to the hardware | ||
1968 | * schedule. | ||
1969 | * | ||
1970 | * Note that we carefully avoid recycling this descriptor until after any | ||
1971 | * completion callback runs, so that it won't be reused quickly. That is, | ||
1972 | * assuming (a) no more than two urbs per frame on this endpoint, and also | ||
1973 | * (b) only this endpoint's completions submit URBs. It seems some silicon | ||
1974 | * corrupts things if you reuse completed descriptors very quickly... | ||
1975 | */ | ||
1953 | static unsigned | 1976 | static unsigned |
1954 | sitd_complete ( | 1977 | sitd_complete ( |
1955 | struct ehci_hcd *ehci, | 1978 | struct ehci_hcd *ehci, |
@@ -1961,6 +1984,7 @@ sitd_complete ( | |||
1961 | int urb_index = -1; | 1984 | int urb_index = -1; |
1962 | struct ehci_iso_stream *stream = sitd->stream; | 1985 | struct ehci_iso_stream *stream = sitd->stream; |
1963 | struct usb_device *dev; | 1986 | struct usb_device *dev; |
1987 | unsigned retval = false; | ||
1964 | 1988 | ||
1965 | urb_index = sitd->index; | 1989 | urb_index = sitd->index; |
1966 | desc = &urb->iso_frame_desc [urb_index]; | 1990 | desc = &urb->iso_frame_desc [urb_index]; |
@@ -1981,17 +2005,11 @@ sitd_complete ( | |||
1981 | desc->status = 0; | 2005 | desc->status = 0; |
1982 | desc->actual_length = desc->length - SITD_LENGTH (t); | 2006 | desc->actual_length = desc->length - SITD_LENGTH (t); |
1983 | } | 2007 | } |
1984 | |||
1985 | usb_put_urb (urb); | ||
1986 | sitd->urb = NULL; | ||
1987 | sitd->stream = NULL; | ||
1988 | list_move (&sitd->sitd_list, &stream->free_list); | ||
1989 | stream->depth -= stream->interval << 3; | 2008 | stream->depth -= stream->interval << 3; |
1990 | iso_stream_put (ehci, stream); | ||
1991 | 2009 | ||
1992 | /* handle completion now? */ | 2010 | /* handle completion now? */ |
1993 | if ((urb_index + 1) != urb->number_of_packets) | 2011 | if ((urb_index + 1) != urb->number_of_packets) |
1994 | return 0; | 2012 | goto done; |
1995 | 2013 | ||
1996 | /* ASSERT: it's really the last sitd for this urb | 2014 | /* ASSERT: it's really the last sitd for this urb |
1997 | list_for_each_entry (sitd, &stream->td_list, sitd_list) | 2015 | list_for_each_entry (sitd, &stream->td_list, sitd_list) |
@@ -2001,6 +2019,7 @@ sitd_complete ( | |||
2001 | /* give urb back to the driver */ | 2019 | /* give urb back to the driver */ |
2002 | dev = urb->dev; | 2020 | dev = urb->dev; |
2003 | ehci_urb_done(ehci, urb, 0); | 2021 | ehci_urb_done(ehci, urb, 0); |
2022 | retval = true; | ||
2004 | urb = NULL; | 2023 | urb = NULL; |
2005 | 2024 | ||
2006 | /* defer stopping schedule; completion can submit */ | 2025 | /* defer stopping schedule; completion can submit */ |
@@ -2018,8 +2037,15 @@ sitd_complete ( | |||
2018 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); | 2037 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); |
2019 | } | 2038 | } |
2020 | iso_stream_put (ehci, stream); | 2039 | iso_stream_put (ehci, stream); |
2040 | /* OK to recycle this SITD now that its completion callback ran. */ | ||
2041 | done: | ||
2042 | usb_put_urb(urb); | ||
2043 | sitd->urb = NULL; | ||
2044 | sitd->stream = NULL; | ||
2045 | list_move(&sitd->sitd_list, &stream->free_list); | ||
2046 | iso_stream_put(ehci, stream); | ||
2021 | 2047 | ||
2022 | return 1; | 2048 | return retval; |
2023 | } | 2049 | } |
2024 | 2050 | ||
2025 | 2051 | ||