diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 12 | ||||
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 53 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 3 |
3 files changed, 16 insertions, 52 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 98b945840c9e..fb1966cf5649 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -1085,8 +1085,14 @@ rescan: | |||
1085 | * accelerate iso completions ... so spin a while. | 1085 | * accelerate iso completions ... so spin a while. |
1086 | */ | 1086 | */ |
1087 | if (qh->hw == NULL) { | 1087 | if (qh->hw == NULL) { |
1088 | ehci_vdbg (ehci, "iso delay\n"); | 1088 | struct ehci_iso_stream *stream = ep->hcpriv; |
1089 | goto idle_timeout; | 1089 | |
1090 | if (!list_empty(&stream->td_list)) | ||
1091 | goto idle_timeout; | ||
1092 | |||
1093 | /* BUG_ON(!list_empty(&stream->free_list)); */ | ||
1094 | kfree(stream); | ||
1095 | goto done; | ||
1090 | } | 1096 | } |
1091 | 1097 | ||
1092 | if (ehci->rh_state < EHCI_RH_RUNNING) | 1098 | if (ehci->rh_state < EHCI_RH_RUNNING) |
@@ -1127,8 +1133,8 @@ idle_timeout: | |||
1127 | list_empty (&qh->qtd_list) ? "" : "(has tds)"); | 1133 | list_empty (&qh->qtd_list) ? "" : "(has tds)"); |
1128 | break; | 1134 | break; |
1129 | } | 1135 | } |
1136 | done: | ||
1130 | ep->hcpriv = NULL; | 1137 | ep->hcpriv = NULL; |
1131 | done: | ||
1132 | spin_unlock_irqrestore (&ehci->lock, flags); | 1138 | spin_unlock_irqrestore (&ehci->lock, flags); |
1133 | } | 1139 | } |
1134 | 1140 | ||
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 1e4f13c11b6a..11b2f21d7ac1 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -934,7 +934,6 @@ iso_stream_alloc (gfp_t mem_flags) | |||
934 | INIT_LIST_HEAD(&stream->td_list); | 934 | INIT_LIST_HEAD(&stream->td_list); |
935 | INIT_LIST_HEAD(&stream->free_list); | 935 | INIT_LIST_HEAD(&stream->free_list); |
936 | stream->next_uframe = -1; | 936 | stream->next_uframe = -1; |
937 | stream->refcount = 1; | ||
938 | } | 937 | } |
939 | return stream; | 938 | return stream; |
940 | } | 939 | } |
@@ -1034,32 +1033,6 @@ iso_stream_init ( | |||
1034 | stream->maxp = maxp; | 1033 | stream->maxp = maxp; |
1035 | } | 1034 | } |
1036 | 1035 | ||
1037 | static void | ||
1038 | iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream) | ||
1039 | { | ||
1040 | stream->refcount--; | ||
1041 | |||
1042 | /* free whenever just a dev->ep reference remains. | ||
1043 | * not like a QH -- no persistent state (toggle, halt) | ||
1044 | */ | ||
1045 | if (stream->refcount == 1) { | ||
1046 | // BUG_ON (!list_empty(&stream->td_list)); | ||
1047 | |||
1048 | if (stream->ep) | ||
1049 | stream->ep->hcpriv = NULL; | ||
1050 | |||
1051 | kfree(stream); | ||
1052 | } | ||
1053 | } | ||
1054 | |||
1055 | static inline struct ehci_iso_stream * | ||
1056 | iso_stream_get (struct ehci_iso_stream *stream) | ||
1057 | { | ||
1058 | if (likely (stream != NULL)) | ||
1059 | stream->refcount++; | ||
1060 | return stream; | ||
1061 | } | ||
1062 | |||
1063 | static struct ehci_iso_stream * | 1036 | static struct ehci_iso_stream * |
1064 | iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) | 1037 | iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) |
1065 | { | 1038 | { |
@@ -1080,7 +1053,6 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) | |||
1080 | if (unlikely (stream == NULL)) { | 1053 | if (unlikely (stream == NULL)) { |
1081 | stream = iso_stream_alloc(GFP_ATOMIC); | 1054 | stream = iso_stream_alloc(GFP_ATOMIC); |
1082 | if (likely (stream != NULL)) { | 1055 | if (likely (stream != NULL)) { |
1083 | /* dev->ep owns the initial refcount */ | ||
1084 | ep->hcpriv = stream; | 1056 | ep->hcpriv = stream; |
1085 | stream->ep = ep; | 1057 | stream->ep = ep; |
1086 | iso_stream_init(ehci, stream, urb->dev, urb->pipe, | 1058 | iso_stream_init(ehci, stream, urb->dev, urb->pipe, |
@@ -1095,9 +1067,6 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) | |||
1095 | stream = NULL; | 1067 | stream = NULL; |
1096 | } | 1068 | } |
1097 | 1069 | ||
1098 | /* caller guarantees an eventual matching iso_stream_put */ | ||
1099 | stream = iso_stream_get (stream); | ||
1100 | |||
1101 | spin_unlock_irqrestore (&ehci->lock, flags); | 1070 | spin_unlock_irqrestore (&ehci->lock, flags); |
1102 | return stream; | 1071 | return stream; |
1103 | } | 1072 | } |
@@ -1611,7 +1580,7 @@ static void itd_link_urb( | |||
1611 | itd = list_entry (iso_sched->td_list.next, | 1580 | itd = list_entry (iso_sched->td_list.next, |
1612 | struct ehci_itd, itd_list); | 1581 | struct ehci_itd, itd_list); |
1613 | list_move_tail (&itd->itd_list, &stream->td_list); | 1582 | list_move_tail (&itd->itd_list, &stream->td_list); |
1614 | itd->stream = iso_stream_get (stream); | 1583 | itd->stream = stream; |
1615 | itd->urb = urb; | 1584 | itd->urb = urb; |
1616 | itd_init (ehci, stream, itd); | 1585 | itd_init (ehci, stream, itd); |
1617 | } | 1586 | } |
@@ -1735,7 +1704,6 @@ itd_complete ( | |||
1735 | dev->devpath, stream->bEndpointAddress & 0x0f, | 1704 | dev->devpath, stream->bEndpointAddress & 0x0f, |
1736 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); | 1705 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); |
1737 | } | 1706 | } |
1738 | iso_stream_put (ehci, stream); | ||
1739 | 1707 | ||
1740 | done: | 1708 | done: |
1741 | itd->urb = NULL; | 1709 | itd->urb = NULL; |
@@ -1750,7 +1718,6 @@ done: | |||
1750 | start_free_itds(ehci); | 1718 | start_free_itds(ehci); |
1751 | } | 1719 | } |
1752 | 1720 | ||
1753 | iso_stream_put(ehci, stream); | ||
1754 | return retval; | 1721 | return retval; |
1755 | } | 1722 | } |
1756 | 1723 | ||
@@ -1807,12 +1774,9 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, | |||
1807 | itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); | 1774 | itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); |
1808 | else | 1775 | else |
1809 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); | 1776 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); |
1810 | done_not_linked: | 1777 | done_not_linked: |
1811 | spin_unlock_irqrestore (&ehci->lock, flags); | 1778 | spin_unlock_irqrestore (&ehci->lock, flags); |
1812 | 1779 | done: | |
1813 | done: | ||
1814 | if (unlikely (status < 0)) | ||
1815 | iso_stream_put (ehci, stream); | ||
1816 | return status; | 1780 | return status; |
1817 | } | 1781 | } |
1818 | 1782 | ||
@@ -2028,7 +1992,7 @@ static void sitd_link_urb( | |||
2028 | sitd = list_entry (sched->td_list.next, | 1992 | sitd = list_entry (sched->td_list.next, |
2029 | struct ehci_sitd, sitd_list); | 1993 | struct ehci_sitd, sitd_list); |
2030 | list_move_tail (&sitd->sitd_list, &stream->td_list); | 1994 | list_move_tail (&sitd->sitd_list, &stream->td_list); |
2031 | sitd->stream = iso_stream_get (stream); | 1995 | sitd->stream = stream; |
2032 | sitd->urb = urb; | 1996 | sitd->urb = urb; |
2033 | 1997 | ||
2034 | sitd_patch(ehci, stream, sitd, sched, packet); | 1998 | sitd_patch(ehci, stream, sitd, sched, packet); |
@@ -2126,7 +2090,6 @@ sitd_complete ( | |||
2126 | dev->devpath, stream->bEndpointAddress & 0x0f, | 2090 | dev->devpath, stream->bEndpointAddress & 0x0f, |
2127 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); | 2091 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); |
2128 | } | 2092 | } |
2129 | iso_stream_put (ehci, stream); | ||
2130 | 2093 | ||
2131 | done: | 2094 | done: |
2132 | sitd->urb = NULL; | 2095 | sitd->urb = NULL; |
@@ -2141,7 +2104,6 @@ done: | |||
2141 | start_free_itds(ehci); | 2104 | start_free_itds(ehci); |
2142 | } | 2105 | } |
2143 | 2106 | ||
2144 | iso_stream_put(ehci, stream); | ||
2145 | return retval; | 2107 | return retval; |
2146 | } | 2108 | } |
2147 | 2109 | ||
@@ -2195,12 +2157,9 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, | |||
2195 | sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); | 2157 | sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); |
2196 | else | 2158 | else |
2197 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); | 2159 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); |
2198 | done_not_linked: | 2160 | done_not_linked: |
2199 | spin_unlock_irqrestore (&ehci->lock, flags); | 2161 | spin_unlock_irqrestore (&ehci->lock, flags); |
2200 | 2162 | done: | |
2201 | done: | ||
2202 | if (status < 0) | ||
2203 | iso_stream_put (ehci, stream); | ||
2204 | return status; | 2163 | return status; |
2205 | } | 2164 | } |
2206 | 2165 | ||
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index bcfbb175e2b4..755e30b0000b 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -386,7 +386,7 @@ struct ehci_qh_hw { | |||
386 | } __attribute__ ((aligned(32))); | 386 | } __attribute__ ((aligned(32))); |
387 | 387 | ||
388 | struct ehci_qh { | 388 | struct ehci_qh { |
389 | struct ehci_qh_hw *hw; | 389 | struct ehci_qh_hw *hw; /* Must come first */ |
390 | /* the rest is HCD-private */ | 390 | /* the rest is HCD-private */ |
391 | dma_addr_t qh_dma; /* address of qh */ | 391 | dma_addr_t qh_dma; /* address of qh */ |
392 | union ehci_shadow qh_next; /* ptr to qh; or periodic */ | 392 | union ehci_shadow qh_next; /* ptr to qh; or periodic */ |
@@ -453,7 +453,6 @@ struct ehci_iso_stream { | |||
453 | /* first field matches ehci_hq, but is NULL */ | 453 | /* first field matches ehci_hq, but is NULL */ |
454 | struct ehci_qh_hw *hw; | 454 | struct ehci_qh_hw *hw; |
455 | 455 | ||
456 | u32 refcount; | ||
457 | u8 bEndpointAddress; | 456 | u8 bEndpointAddress; |
458 | u8 highspeed; | 457 | u8 highspeed; |
459 | struct list_head td_list; /* queued itds/sitds */ | 458 | struct list_head td_list; /* queued itds/sitds */ |