aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-sched.c')
-rw-r--r--drivers/usb/host/ehci-sched.c137
1 files changed, 39 insertions, 98 deletions
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index eec8446f8ded..1e4f13c11b6a 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1045,31 +1045,6 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
1045 if (stream->refcount == 1) { 1045 if (stream->refcount == 1) {
1046 // BUG_ON (!list_empty(&stream->td_list)); 1046 // BUG_ON (!list_empty(&stream->td_list));
1047 1047
1048 while (!list_empty (&stream->free_list)) {
1049 struct list_head *entry;
1050
1051 entry = stream->free_list.next;
1052 list_del (entry);
1053
1054 /* knows about ITD vs SITD */
1055 if (stream->highspeed) {
1056 struct ehci_itd *itd;
1057
1058 itd = list_entry (entry, struct ehci_itd,
1059 itd_list);
1060 dma_pool_free (ehci->itd_pool, itd,
1061 itd->itd_dma);
1062 } else {
1063 struct ehci_sitd *sitd;
1064
1065 sitd = list_entry (entry, struct ehci_sitd,
1066 sitd_list);
1067 dma_pool_free (ehci->sitd_pool, sitd,
1068 sitd->sitd_dma);
1069 }
1070 }
1071
1072 stream->bEndpointAddress &= 0x0f;
1073 if (stream->ep) 1048 if (stream->ep)
1074 stream->ep->hcpriv = NULL; 1049 stream->ep->hcpriv = NULL;
1075 1050
@@ -1230,17 +1205,19 @@ itd_urb_transaction (
1230 spin_lock_irqsave (&ehci->lock, flags); 1205 spin_lock_irqsave (&ehci->lock, flags);
1231 for (i = 0; i < num_itds; i++) { 1206 for (i = 0; i < num_itds; i++) {
1232 1207
1233 /* free_list.next might be cache-hot ... but maybe 1208 /*
1234 * the HC caches it too. avoid that issue for now. 1209 * Use iTDs from the free list, but not iTDs that may
1210 * still be in use by the hardware.
1235 */ 1211 */
1236 1212 if (likely(!list_empty(&stream->free_list))) {
1237 /* prefer previously-allocated itds */ 1213 itd = list_first_entry(&stream->free_list,
1238 if (likely (!list_empty(&stream->free_list))) {
1239 itd = list_entry (stream->free_list.prev,
1240 struct ehci_itd, itd_list); 1214 struct ehci_itd, itd_list);
1215 if (itd->frame == ehci->clock_frame)
1216 goto alloc_itd;
1241 list_del (&itd->itd_list); 1217 list_del (&itd->itd_list);
1242 itd_dma = itd->itd_dma; 1218 itd_dma = itd->itd_dma;
1243 } else { 1219 } else {
1220 alloc_itd:
1244 spin_unlock_irqrestore (&ehci->lock, flags); 1221 spin_unlock_irqrestore (&ehci->lock, flags);
1245 itd = dma_pool_alloc (ehci->itd_pool, mem_flags, 1222 itd = dma_pool_alloc (ehci->itd_pool, mem_flags,
1246 &itd_dma); 1223 &itd_dma);
@@ -1762,24 +1739,18 @@ itd_complete (
1762 1739
1763done: 1740done:
1764 itd->urb = NULL; 1741 itd->urb = NULL;
1765 if (ehci->clock_frame != itd->frame || itd->index[7] != -1) { 1742
1766 /* OK to recycle this ITD now. */ 1743 /* Add to the end of the free list for later reuse */
1767 itd->stream = NULL; 1744 list_move_tail(&itd->itd_list, &stream->free_list);
1768 list_move(&itd->itd_list, &stream->free_list); 1745
1769 iso_stream_put(ehci, stream); 1746 /* Recycle the iTDs when the pipeline is empty (ep no longer in use) */
1770 } else { 1747 if (list_empty(&stream->td_list)) {
1771 /* HW might remember this ITD, so we can't recycle it yet. 1748 list_splice_tail_init(&stream->free_list,
1772 * Move it to a safe place until a new frame starts. 1749 &ehci->cached_itd_list);
1773 */ 1750 start_free_itds(ehci);
1774 list_move(&itd->itd_list, &ehci->cached_itd_list);
1775 if (stream->refcount == 2) {
1776 /* If iso_stream_put() were called here, stream
1777 * would be freed. Instead, just prevent reuse.
1778 */
1779 stream->ep->hcpriv = NULL;
1780 stream->ep = NULL;
1781 }
1782 } 1751 }
1752
1753 iso_stream_put(ehci, stream);
1783 return retval; 1754 return retval;
1784} 1755}
1785 1756
@@ -1930,17 +1901,19 @@ sitd_urb_transaction (
1930 * means we never need two sitds for full speed packets. 1901 * means we never need two sitds for full speed packets.
1931 */ 1902 */
1932 1903
1933 /* free_list.next might be cache-hot ... but maybe 1904 /*
1934 * the HC caches it too. avoid that issue for now. 1905 * Use siTDs from the free list, but not siTDs that may
1906 * still be in use by the hardware.
1935 */ 1907 */
1936 1908 if (likely(!list_empty(&stream->free_list))) {
1937 /* prefer previously-allocated sitds */ 1909 sitd = list_first_entry(&stream->free_list,
1938 if (!list_empty(&stream->free_list)) {
1939 sitd = list_entry (stream->free_list.prev,
1940 struct ehci_sitd, sitd_list); 1910 struct ehci_sitd, sitd_list);
1911 if (sitd->frame == ehci->clock_frame)
1912 goto alloc_sitd;
1941 list_del (&sitd->sitd_list); 1913 list_del (&sitd->sitd_list);
1942 sitd_dma = sitd->sitd_dma; 1914 sitd_dma = sitd->sitd_dma;
1943 } else { 1915 } else {
1916 alloc_sitd:
1944 spin_unlock_irqrestore (&ehci->lock, flags); 1917 spin_unlock_irqrestore (&ehci->lock, flags);
1945 sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags, 1918 sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags,
1946 &sitd_dma); 1919 &sitd_dma);
@@ -2157,24 +2130,18 @@ sitd_complete (
2157 2130
2158done: 2131done:
2159 sitd->urb = NULL; 2132 sitd->urb = NULL;
2160 if (ehci->clock_frame != sitd->frame) { 2133
2161 /* OK to recycle this SITD now. */ 2134 /* Add to the end of the free list for later reuse */
2162 sitd->stream = NULL; 2135 list_move_tail(&sitd->sitd_list, &stream->free_list);
2163 list_move(&sitd->sitd_list, &stream->free_list); 2136
2164 iso_stream_put(ehci, stream); 2137 /* Recycle the siTDs when the pipeline is empty (ep no longer in use) */
2165 } else { 2138 if (list_empty(&stream->td_list)) {
2166 /* HW might remember this SITD, so we can't recycle it yet. 2139 list_splice_tail_init(&stream->free_list,
2167 * Move it to a safe place until a new frame starts. 2140 &ehci->cached_sitd_list);
2168 */ 2141 start_free_itds(ehci);
2169 list_move(&sitd->sitd_list, &ehci->cached_sitd_list);
2170 if (stream->refcount == 2) {
2171 /* If iso_stream_put() were called here, stream
2172 * would be freed. Instead, just prevent reuse.
2173 */
2174 stream->ep->hcpriv = NULL;
2175 stream->ep = NULL;
2176 }
2177 } 2142 }
2143
2144 iso_stream_put(ehci, stream);
2178 return retval; 2145 return retval;
2179} 2146}
2180 2147
@@ -2239,28 +2206,6 @@ done:
2239 2206
2240/*-------------------------------------------------------------------------*/ 2207/*-------------------------------------------------------------------------*/
2241 2208
2242static void free_cached_lists(struct ehci_hcd *ehci)
2243{
2244 struct ehci_itd *itd, *n;
2245 struct ehci_sitd *sitd, *sn;
2246
2247 list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) {
2248 struct ehci_iso_stream *stream = itd->stream;
2249 itd->stream = NULL;
2250 list_move(&itd->itd_list, &stream->free_list);
2251 iso_stream_put(ehci, stream);
2252 }
2253
2254 list_for_each_entry_safe(sitd, sn, &ehci->cached_sitd_list, sitd_list) {
2255 struct ehci_iso_stream *stream = sitd->stream;
2256 sitd->stream = NULL;
2257 list_move(&sitd->sitd_list, &stream->free_list);
2258 iso_stream_put(ehci, stream);
2259 }
2260}
2261
2262/*-------------------------------------------------------------------------*/
2263
2264static void 2209static void
2265scan_periodic (struct ehci_hcd *ehci) 2210scan_periodic (struct ehci_hcd *ehci)
2266{ 2211{
@@ -2282,10 +2227,7 @@ scan_periodic (struct ehci_hcd *ehci)
2282 clock = now_uframe + mod - 1; 2227 clock = now_uframe + mod - 1;
2283 clock_frame = -1; 2228 clock_frame = -1;
2284 } 2229 }
2285 if (ehci->clock_frame != clock_frame) { 2230 ehci->clock_frame = clock_frame;
2286 free_cached_lists(ehci);
2287 ehci->clock_frame = clock_frame;
2288 }
2289 clock &= mod - 1; 2231 clock &= mod - 1;
2290 clock_frame = clock >> 3; 2232 clock_frame = clock >> 3;
2291 ++ehci->periodic_stamp; 2233 ++ehci->periodic_stamp;
@@ -2463,7 +2405,6 @@ restart:
2463 clock = now; 2405 clock = now;
2464 clock_frame = clock >> 3; 2406 clock_frame = clock >> 3;
2465 if (ehci->clock_frame != clock_frame) { 2407 if (ehci->clock_frame != clock_frame) {
2466 free_cached_lists(ehci);
2467 ehci->clock_frame = clock_frame; 2408 ehci->clock_frame = clock_frame;
2468 ++ehci->periodic_stamp; 2409 ++ehci->periodic_stamp;
2469 } 2410 }