11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2001-2004 by David Brownell 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2003 Michal Sojka, for high-speed iso transfers 453bd6a601a87bb6d0df844872bc15fd4e8d127ceDavid Brownell * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify it 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * under the terms of the GNU General Public License as published by the 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Free Software Foundation; either version 2 of the License, or (at your 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * option) any later version. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, but 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for more details. 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software Foundation, 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* this file is part of ehci-hcd.c */ 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * EHCI scheduled transaction support: interrupt, iso, split iso 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These are called "periodic" transactions in the EHCI spec. 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that for interrupt transfers, the QH/QTD manipulation is shared 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with the "asynchronous" transaction support (control/bulk transfers). 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The only real difference is in how interrupt transfers are scheduled. 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For ISO, we make an "iso_stream" head to serve the same role as a QH. 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * It keeps track of every ITD (or SITD) that's linked, and holds enough 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pre-calculated schedule data to make appending to the queue be quick. 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ehci_get_frame (struct usb_hcd *hcd); 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3968aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern#ifdef CONFIG_PCI 4068aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern 4168aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Sternstatic unsigned ehci_read_frame_index(struct ehci_hcd *ehci) 4268aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern{ 4368aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern unsigned uf; 4468aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern 4568aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern /* 4668aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern * The MosChip MCS9990 controller updates its microframe counter 4768aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern * a little before the frame counter, and occasionally we will read 4868aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern * the invalid intermediate value. Avoid problems by checking the 4968aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern * microframe number (the low-order 3 bits); if they are 0 then 5068aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern * re-read the register to get the correct value. 5168aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern */ 5268aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern uf = ehci_readl(ehci, &ehci->regs->frame_index); 5368aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern if (unlikely(ehci->frame_index_bug && ((uf & 7) == 0))) 5468aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern uf = ehci_readl(ehci, &ehci->regs->frame_index); 5568aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern return uf; 5668aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern} 5768aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern 5868aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern#endif 5968aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * periodic_next_shadow - return "next" pointer on shadow list 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @periodic: host pointer to qh/itd/sitd 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @tag: hardware tag for type of this record 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic union ehci_shadow * 686dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roeseperiodic_next_shadow(struct ehci_hcd *ehci, union ehci_shadow *periodic, 696dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese __hc32 tag) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 716dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese switch (hc32_to_cpu(ehci, tag)) { 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case Q_TYPE_QH: 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return &periodic->qh->qh_next; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case Q_TYPE_FSTN: 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return &periodic->fstn->fstn_next; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case Q_TYPE_ITD: 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return &periodic->itd->itd_next; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // case Q_TYPE_SITD: 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return &periodic->sitd->sitd_next; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 843807e26d69b9ad3864fe03224ebebc9610d5802eAlek Dustatic __hc32 * 853807e26d69b9ad3864fe03224ebebc9610d5802eAlek Dushadow_next_periodic(struct ehci_hcd *ehci, union ehci_shadow *periodic, 863807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du __hc32 tag) 873807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du{ 883807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du switch (hc32_to_cpu(ehci, tag)) { 893807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du /* our ehci_shadow.qh is actually software part */ 903807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du case Q_TYPE_QH: 913807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du return &periodic->qh->hw->hw_next; 923807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du /* others are hw parts */ 933807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du default: 943807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du return periodic->hw_next; 953807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du } 963807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du} 973807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* caller must hold ehci->lock */ 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1016dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese union ehci_shadow *prev_p = &ehci->pshadow[frame]; 1026dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese __hc32 *hw_p = &ehci->periodic[frame]; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union ehci_shadow here = *prev_p; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* find predecessor of "ptr"; hw and shadow lists are in sync */ 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (here.ptr && here.ptr != ptr) { 1076dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese prev_p = periodic_next_shadow(ehci, prev_p, 1086dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese Q_NEXT_TYPE(ehci, *hw_p)); 1093807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du hw_p = shadow_next_periodic(ehci, &here, 1103807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du Q_NEXT_TYPE(ehci, *hw_p)); 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds here = *prev_p; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* an interrupt entry (at list end) could have been shared */ 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!here.ptr) 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* update shadow and hardware lists ... the old "next" pointers 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * from ptr may still be in use, the caller updates them. 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1206dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese *prev_p = *periodic_next_shadow(ehci, &here, 1216dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese Q_NEXT_TYPE(ehci, *hw_p)); 1223d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu 1233d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu if (!ehci->use_dummy_qh || 1243d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu *shadow_next_periodic(ehci, &here, Q_NEXT_TYPE(ehci, *hw_p)) 1253d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu != EHCI_LIST_END(ehci)) 1263d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu *hw_p = *shadow_next_periodic(ehci, &here, 1273d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu Q_NEXT_TYPE(ehci, *hw_p)); 1283d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu else 1293d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu *hw_p = ehci->dummy->qh_dma; 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* how many of the uframe's 125 usecs are allocated? */ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsperiodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1366dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese __hc32 *hw_p = &ehci->periodic [frame]; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union ehci_shadow *q = &ehci->pshadow [frame]; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned usecs = 0; 1393807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du struct ehci_qh_hw *hw; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (q->ptr) { 1426dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) { 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case Q_TYPE_QH: 1443807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du hw = q->qh->hw; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* is it in the S-mask? */ 1463807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du if (hw->hw_info2 & cpu_to_hc32(ehci, 1 << uframe)) 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usecs += q->qh->usecs; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ... or C-mask? */ 1493807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du if (hw->hw_info2 & cpu_to_hc32(ehci, 1506dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese 1 << (8 + uframe))) 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usecs += q->qh->c_usecs; 1523807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du hw_p = &hw->hw_next; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = &q->qh->qh_next; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // case Q_TYPE_FSTN: 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* for "save place" FSTNs, count the relevant INTR 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bandwidth from the previous frame 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1606dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese if (q->fstn->hw_prev != EHCI_LIST_END(ehci)) { 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_dbg (ehci, "ignoring FSTN cost ...\n"); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_p = &q->fstn->hw_next; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = &q->fstn->fstn_next; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case Q_TYPE_ITD: 1673b6fcfd0664aeac6ae2fd1231f04b3ed24723c1eKarsten Wiese if (q->itd->hw_transaction[uframe]) 1683b6fcfd0664aeac6ae2fd1231f04b3ed24723c1eKarsten Wiese usecs += q->itd->stream->usecs; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_p = &q->itd->hw_next; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = &q->itd->itd_next; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case Q_TYPE_SITD: 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* is it in the S-mask? (count SPLIT, DATA) */ 1746dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese if (q->sitd->hw_uframe & cpu_to_hc32(ehci, 1756dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese 1 << uframe)) { 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (q->sitd->hw_fullspeed_ep & 1776dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese cpu_to_hc32(ehci, 1<<31)) 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usecs += q->sitd->stream->usecs; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else /* worst case for OUT start-split */ 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usecs += HS_USECS_ISO (188); 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ... C-mask? (count CSPLIT, DATA) */ 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (q->sitd->hw_uframe & 1856dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese cpu_to_hc32(ehci, 1 << (8 + uframe))) { 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* worst case for IN complete-split */ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usecs += q->sitd->stream->c_usecs; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_p = &q->sitd->hw_next; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = &q->sitd->sitd_next; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG 196cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov if (usecs > ehci->uframe_periodic_max) 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_err (ehci, "uframe %d sched overrun: %d usecs\n", 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frame * 8 + uframe, usecs); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return usecs; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int same_tt (struct usb_device *dev1, struct usb_device *dev2) 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev1->tt || !dev2->tt) 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev1->tt != dev2->tt) 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev1->tt->multi) 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dev1->ttport == dev2->ttport; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 217ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman#ifdef CONFIG_USB_EHCI_TT_NEWSCHED 218ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 219ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman/* Which uframe does the low/fullspeed transfer start in? 220ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * 221ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * The parameter is the mask of ssplits in "H-frame" terms 222ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * and this returns the transfer start uframe in "B-frame" terms, 223ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * which allows both to match, e.g. a ssplit in "H-frame" uframe 0 224ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * will cause a transfer in "B-frame" uframe 0. "B-frames" lag 225ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * "H-frames" by 1 uframe. See the EHCI spec sec 4.5 and figure 4.7. 226ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman */ 2276dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roesestatic inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask) 228ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman{ 2296dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese unsigned char smask = QH_SMASK & hc32_to_cpu(ehci, mask); 230ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman if (!smask) { 231ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman ehci_err(ehci, "invalid empty smask!\n"); 232ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman /* uframe 7 can't have bw so this will indicate failure */ 233ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman return 7; 234ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman } 235ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman return ffs(smask) - 1; 236ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman} 237ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 238ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetmanstatic const unsigned char 239ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetmanmax_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; 240ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 241ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman/* carryover low/fullspeed bandwidth that crosses uframe boundries */ 242ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetmanstatic inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) 243ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman{ 244ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman int i; 245ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman for (i=0; i<7; i++) { 246ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman if (max_tt_usecs[i] < tt_usecs[i]) { 247ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman tt_usecs[i+1] += tt_usecs[i] - max_tt_usecs[i]; 248ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman tt_usecs[i] = max_tt_usecs[i]; 249ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman } 250ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman } 251ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman} 252ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 253ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman/* How many of the tt's periodic downstream 1000 usecs are allocated? 254ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * 255ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * While this measures the bandwidth in terms of usecs/uframe, 256ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * the low/fullspeed bus has no notion of uframes, so any particular 257ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * low/fullspeed transfer can "carry over" from one uframe to the next, 258ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * since the TT just performs downstream transfers in sequence. 259ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * 260dc0d5c1e5c7532e800fff6e313cd4af44af99976Joe Perches * For example two separate 100 usec transfers can start in the same uframe, 261ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * and the second one would "carry over" 75 usecs into the next uframe. 262ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman */ 263ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetmanstatic void 264ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetmanperiodic_tt_usecs ( 265ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman struct ehci_hcd *ehci, 266ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman struct usb_device *dev, 267ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman unsigned frame, 268ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman unsigned short tt_usecs[8] 269ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman) 270ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman{ 2716dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese __hc32 *hw_p = &ehci->periodic [frame]; 272ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman union ehci_shadow *q = &ehci->pshadow [frame]; 273ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman unsigned char uf; 274ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 275ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman memset(tt_usecs, 0, 16); 276ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 277ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman while (q->ptr) { 2786dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) { 279ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman case Q_TYPE_ITD: 280ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman hw_p = &q->itd->hw_next; 281ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman q = &q->itd->itd_next; 282ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman continue; 283ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman case Q_TYPE_QH: 284ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman if (same_tt(dev, q->qh->dev)) { 2853807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du uf = tt_start_uframe(ehci, q->qh->hw->hw_info2); 286ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman tt_usecs[uf] += q->qh->tt_usecs; 287ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman } 2883807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du hw_p = &q->qh->hw->hw_next; 289ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman q = &q->qh->qh_next; 290ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman continue; 291ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman case Q_TYPE_SITD: 292ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman if (same_tt(dev, q->sitd->urb->dev)) { 293ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman uf = tt_start_uframe(ehci, q->sitd->hw_uframe); 294ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman tt_usecs[uf] += q->sitd->stream->tt_usecs; 295ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman } 296ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman hw_p = &q->sitd->hw_next; 297ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman q = &q->sitd->sitd_next; 298ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman continue; 299ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman // case Q_TYPE_FSTN: 300ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman default: 3016dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese ehci_dbg(ehci, "ignoring periodic frame %d FSTN\n", 3026dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese frame); 303ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman hw_p = &q->fstn->hw_next; 304ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman q = &q->fstn->fstn_next; 305ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman } 306ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman } 307ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 308ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman carryover_tt_bandwidth(tt_usecs); 309ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 310ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman if (max_tt_usecs[7] < tt_usecs[7]) 311ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman ehci_err(ehci, "frame %d tt sched overrun: %d usecs\n", 312ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman frame, tt_usecs[7] - max_tt_usecs[7]); 313ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman} 314ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 315ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman/* 316ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * Return true if the device's tt's downstream bus is available for a 317ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * periodic transfer of the specified length (usecs), starting at the 318ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * specified frame/uframe. Note that (as summarized in section 11.19 319ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * of the usb 2.0 spec) TTs can buffer multiple transactions for each 320ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * uframe. 321ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * 322ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * The uframe parameter is when the fullspeed/lowspeed transfer 323ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * should be executed in "B-frame" terms, which is the same as the 324ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * highspeed ssplit's uframe (which is in "H-frame" terms). For example 325ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * a ssplit in "H-frame" 0 causes a transfer in "B-frame" 0. 326ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * See the EHCI spec sec 4.5 and fig 4.7. 327ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * 328ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * This checks if the full/lowspeed bus, at the specified starting uframe, 329ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * has the specified bandwidth available, according to rules listed 330ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * in USB 2.0 spec section 11.18.1 fig 11-60. 331ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * 332ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * This does not check if the transfer would exceed the max ssplit 333ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * limit of 16, specified in USB 2.0 spec section 11.18.4 requirement #4, 334ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * since proper scheduling limits ssplits to less than 16 per uframe. 335ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman */ 336ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetmanstatic int tt_available ( 337ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman struct ehci_hcd *ehci, 338ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman unsigned period, 339ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman struct usb_device *dev, 340ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman unsigned frame, 341ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman unsigned uframe, 342ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman u16 usecs 343ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman) 344ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman{ 345ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman if ((period == 0) || (uframe >= 7)) /* error */ 346ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman return 0; 347ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 348ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman for (; frame < ehci->periodic_size; frame += period) { 349ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman unsigned short tt_usecs[8]; 350ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 351ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman periodic_tt_usecs (ehci, dev, frame, tt_usecs); 352ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 353ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman ehci_vdbg(ehci, "tt frame %d check %d usecs start uframe %d in" 354ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman " schedule %d/%d/%d/%d/%d/%d/%d/%d\n", 355ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman frame, usecs, uframe, 356ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman tt_usecs[0], tt_usecs[1], tt_usecs[2], tt_usecs[3], 357ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman tt_usecs[4], tt_usecs[5], tt_usecs[6], tt_usecs[7]); 358ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 359ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman if (max_tt_usecs[uframe] <= tt_usecs[uframe]) { 360ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman ehci_vdbg(ehci, "frame %d uframe %d fully scheduled\n", 361ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman frame, uframe); 362ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman return 0; 363ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman } 364ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 365ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman /* special case for isoc transfers larger than 125us: 366ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * the first and each subsequent fully used uframe 367ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * must be empty, so as to not illegally delay 368ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * already scheduled transactions 369ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman */ 370ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman if (125 < usecs) { 371c065c60e83c006611caed23d1320450fcd709398Dan Streetman int ufs = (usecs / 125); 372ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman int i; 373ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman for (i = uframe; i < (uframe + ufs) && i < 8; i++) 374ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman if (0 < tt_usecs[i]) { 375ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman ehci_vdbg(ehci, 376ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman "multi-uframe xfer can't fit " 377ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman "in frame %d uframe %d\n", 378ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman frame, i); 379ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman return 0; 380ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman } 381ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman } 382ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 383ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman tt_usecs[uframe] += usecs; 384ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 385ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman carryover_tt_bandwidth(tt_usecs); 386ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 387ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman /* fail if the carryover pushed bw past the last uframe's limit */ 388ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman if (max_tt_usecs[7] < tt_usecs[7]) { 389ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman ehci_vdbg(ehci, 390ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman "tt unavailable usecs %d frame %d uframe %d\n", 391ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman usecs, frame, uframe); 392ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman return 0; 393ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman } 394ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman } 395ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 396ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman return 1; 397ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman} 398ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 399ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman#else 400ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* return true iff the device's transaction translator is available 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for a periodic transfer starting at the specified frame, using 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * all the uframes in the mask. 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int tt_no_collision ( 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_hcd *ehci, 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned period, 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_device *dev, 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned frame, 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 uf_mask 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (period == 0) /* error */ 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* note bandwidth wastage: split never follows csplit 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (different dev or endpoint) until the next uframe. 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * calling convention doesn't make that distinction. 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (; frame < ehci->periodic_size; frame += period) { 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union ehci_shadow here; 4226dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese __hc32 type; 4233807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du struct ehci_qh_hw *hw; 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds here = ehci->pshadow [frame]; 4266dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese type = Q_NEXT_TYPE(ehci, ehci->periodic [frame]); 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (here.ptr) { 4286dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese switch (hc32_to_cpu(ehci, type)) { 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case Q_TYPE_ITD: 4306dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese type = Q_NEXT_TYPE(ehci, here.itd->hw_next); 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds here = here.itd->itd_next; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case Q_TYPE_QH: 4343807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du hw = here.qh->hw; 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (same_tt (dev, here.qh->dev)) { 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 mask; 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4386dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese mask = hc32_to_cpu(ehci, 4393807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du hw->hw_info2); 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* "knows" no gap is needed */ 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= mask >> 8; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mask & uf_mask) 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4453807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du type = Q_NEXT_TYPE(ehci, hw->hw_next); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds here = here.qh->qh_next; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case Q_TYPE_SITD: 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (same_tt (dev, here.sitd->urb->dev)) { 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 mask; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4526dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese mask = hc32_to_cpu(ehci, here.sitd 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ->hw_uframe); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXME assumes no gap for IN! */ 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= mask >> 8; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mask & uf_mask) 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4596dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese type = Q_NEXT_TYPE(ehci, here.sitd->hw_next); 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds here = here.sitd->sitd_next; 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // case Q_TYPE_FSTN: 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_dbg (ehci, 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "periodic frame %d bogus type %d\n", 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frame, type); 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* collision or error */ 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* no collision */ 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 478ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman#endif /* CONFIG_USB_EHCI_TT_NEWSCHED */ 479ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int enable_periodic (struct ehci_hcd *ehci) 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 cmd; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status; 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 48701c17142659c02d8cd4c67acdd8358180c5c4fb6David Brownell if (ehci->periodic_sched++) 48801c17142659c02d8cd4c67acdd8358180c5c4fb6David Brownell return 0; 48901c17142659c02d8cd4c67acdd8358180c5c4fb6David Brownell 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* did clearing PSE did take effect yet? 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * takes effect only at frame boundaries... 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 493c765d4cad977f7e454a53d5bca5a942156b2d94cKarsten Wiese status = handshake_on_error_set_halt(ehci, &ehci->regs->status, 494c765d4cad977f7e454a53d5bca5a942156b2d94cKarsten Wiese STS_PSS, 0, 9 * 125); 49569fff59de4d844f8b4c2454c3c23d32b69dcbfd7Alan Stern if (status) { 49669fff59de4d844f8b4c2454c3c23d32b69dcbfd7Alan Stern usb_hc_died(ehci_to_hcd(ehci)); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return status; 49869fff59de4d844f8b4c2454c3c23d32b69dcbfd7Alan Stern } 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 500083522d76662cda71328df1f3d75e5a9057c7c9fBenjamin Herrenschmidt cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE; 501083522d76662cda71328df1f3d75e5a9057c7c9fBenjamin Herrenschmidt ehci_writel(ehci, cmd, &ehci->regs->command); 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* posted write ... PSS happens later */ 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* make sure ehci_work scans these */ 50568aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern ehci->next_uframe = ehci_read_frame_index(ehci) 506083522d76662cda71328df1f3d75e5a9057c7c9fBenjamin Herrenschmidt % (ehci->periodic_size << 3); 507ee4ecb8ac63a5792bec448037d4b82ec4144f94bOliver Neukum if (unlikely(ehci->broken_periodic)) 508ee4ecb8ac63a5792bec448037d4b82ec4144f94bOliver Neukum ehci->last_periodic_enable = ktime_get_real(); 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int disable_periodic (struct ehci_hcd *ehci) 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 cmd; 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51701c17142659c02d8cd4c67acdd8358180c5c4fb6David Brownell if (--ehci->periodic_sched) 51801c17142659c02d8cd4c67acdd8358180c5c4fb6David Brownell return 0; 51901c17142659c02d8cd4c67acdd8358180c5c4fb6David Brownell 520ee4ecb8ac63a5792bec448037d4b82ec4144f94bOliver Neukum if (unlikely(ehci->broken_periodic)) { 521ee4ecb8ac63a5792bec448037d4b82ec4144f94bOliver Neukum /* delay experimentally determined */ 522ee4ecb8ac63a5792bec448037d4b82ec4144f94bOliver Neukum ktime_t safe = ktime_add_us(ehci->last_periodic_enable, 1000); 523ee4ecb8ac63a5792bec448037d4b82ec4144f94bOliver Neukum ktime_t now = ktime_get_real(); 524ee4ecb8ac63a5792bec448037d4b82ec4144f94bOliver Neukum s64 delay = ktime_us_delta(safe, now); 525ee4ecb8ac63a5792bec448037d4b82ec4144f94bOliver Neukum 526ee4ecb8ac63a5792bec448037d4b82ec4144f94bOliver Neukum if (unlikely(delay > 0)) 527ee4ecb8ac63a5792bec448037d4b82ec4144f94bOliver Neukum udelay(delay); 528ee4ecb8ac63a5792bec448037d4b82ec4144f94bOliver Neukum } 529ee4ecb8ac63a5792bec448037d4b82ec4144f94bOliver Neukum 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* did setting PSE not take effect yet? 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * takes effect only at frame boundaries... 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 533c765d4cad977f7e454a53d5bca5a942156b2d94cKarsten Wiese status = handshake_on_error_set_halt(ehci, &ehci->regs->status, 534c765d4cad977f7e454a53d5bca5a942156b2d94cKarsten Wiese STS_PSS, STS_PSS, 9 * 125); 53569fff59de4d844f8b4c2454c3c23d32b69dcbfd7Alan Stern if (status) { 53669fff59de4d844f8b4c2454c3c23d32b69dcbfd7Alan Stern usb_hc_died(ehci_to_hcd(ehci)); 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return status; 53869fff59de4d844f8b4c2454c3c23d32b69dcbfd7Alan Stern } 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 540083522d76662cda71328df1f3d75e5a9057c7c9fBenjamin Herrenschmidt cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE; 541083522d76662cda71328df1f3d75e5a9057c7c9fBenjamin Herrenschmidt ehci_writel(ehci, cmd, &ehci->regs->command); 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* posted write ... */ 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5440e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern free_cached_lists(ehci); 545d63c66d2d08f52487f3ef32f1c9b1231d848966bDmitri Epshtein 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci->next_uframe = -1; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* periodic schedule slots have iso tds (normal or split) first, then a 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sparse tree for active interrupt transfers. 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this just links in a qh; caller guarantees uframe masks are set right. 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * no FSTN support (yet; ehci 0.96+) 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned i; 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned period = qh->period; 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg (&qh->dev->dev, 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "link qh%d-%04x/%p start %d [%d/%d us]\n", 5653807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du period, hc32_to_cpup(ehci, &qh->hw->hw_info2) 5663807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du & (QH_CMASK | QH_SMASK), 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh, qh->start, qh->usecs, qh->c_usecs); 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* high bandwidth, or otherwise every microframe */ 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (period == 0) 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds period = 1; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = qh->start; i < ehci->periodic_size; i += period) { 5746dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese union ehci_shadow *prev = &ehci->pshadow[i]; 5756dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese __hc32 *hw_p = &ehci->periodic[i]; 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union ehci_shadow here = *prev; 5776dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese __hc32 type = 0; 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* skip the iso nodes at list head */ 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (here.ptr) { 5816dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese type = Q_NEXT_TYPE(ehci, *hw_p); 5826dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese if (type == cpu_to_hc32(ehci, Q_TYPE_QH)) 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5846dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese prev = periodic_next_shadow(ehci, prev, type); 5853807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du hw_p = shadow_next_periodic(ehci, &here, type); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds here = *prev; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* sorting each branch by period (slow-->fast) 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * enables sharing interior tree nodes 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (here.ptr && qh != here.qh) { 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (qh->period > here.qh->period) 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev = &here.qh->qh_next; 5963807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du hw_p = &here.qh->hw->hw_next; 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds here = *prev; 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* link in this qh, unless some earlier pass did that */ 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (qh != here.qh) { 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh->qh_next = here; 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (here.qh) 6033807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du qh->hw->hw_next = *hw_p; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb (); 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prev->qh = qh; 6066dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese *hw_p = QH_NEXT (ehci, qh->qh_dma); 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh->qh_state = QH_STATE_LINKED; 610ef4638f955f2c4a667c8af20769d03f5ed3781caAlan Stern qh->xacterrs = 0; 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh_get (qh); 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* update per-qh bandwidth for usbfs */ 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ? ((qh->usecs + qh->c_usecs) / qh->period) 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : (qh->usecs * 8); 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* maybe enable periodic schedule processing */ 61901c17142659c02d8cd4c67acdd8358180c5c4fb6David Brownell return enable_periodic(ehci); 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 62201c17142659c02d8cd4c67acdd8358180c5c4fb6David Brownellstatic int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned i; 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned period; 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // FIXME: 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // IF this isn't high speed 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // and this qh is active in the current uframe 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // (and overlay token SplitXstate is false?) 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // THEN 632551509d267905705f6d723e51ec706916f06b859Harvey Harrison // qh->hw_info1 |= cpu_to_hc32(1 << 7 /* "ignore" */); 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* high bandwidth, or otherwise part of every microframe */ 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((period = qh->period) == 0) 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds period = 1; 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = qh->start; i < ehci->periodic_size; i += period) 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds periodic_unlink (ehci, i, qh); 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* update per-qh bandwidth for usbfs */ 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->period 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ? ((qh->usecs + qh->c_usecs) / qh->period) 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : (qh->usecs * 8); 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_dbg (&qh->dev->dev, 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "unlink qh%d-%04x/%p start %d [%d/%d us]\n", 6487dedacf4270a810fadcca887ac85d267b5f1882dDavid Brownell qh->period, 6493807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du hc32_to_cpup(ehci, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK), 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh, qh->start, qh->usecs, qh->c_usecs); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* qh->qh_next still "live" to HC */ 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh->qh_state = QH_STATE_UNLINK; 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh->qh_next.ptr = NULL; 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh_put (qh); 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* maybe turn off periodic schedule */ 65801c17142659c02d8cd4c67acdd8358180c5c4fb6David Brownell return disable_periodic(ehci); 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 663a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern unsigned wait; 664a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern struct ehci_qh_hw *hw = qh->hw; 665a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern int rc; 666a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern 667a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern /* If the QH isn't linked then there's nothing we can do 668a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern * unless we were called during a giveback, in which case 669a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern * qh_completions() has to deal with it. 670a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern */ 671a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern if (qh->qh_state != QH_STATE_LINKED) { 672a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern if (qh->qh_state == QH_STATE_COMPLETING) 673a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern qh->needs_rescan = 1; 674a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern return; 675a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern } 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh_unlink_periodic (ehci, qh); 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* simple/paranoid: always delay, expecting the HC needs to read 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * qh->hw_next or finish a writeback after SPLIT/CSPLIT ... and 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * expect khubd to clean up after any CSPLITs we won't issue. 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * active high speed queues may need bigger delays... 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (list_empty (&qh->qtd_list) 6856dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese || (cpu_to_hc32(ehci, QH_CMASK) 6863807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du & hw->hw_info2) != 0) 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait = 2; 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait = 55; /* worst case: 3 * 1024 */ 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay (wait); 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh->qh_state = QH_STATE_IDLE; 6933807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du hw->hw_next = EHCI_LIST_END(ehci); 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb (); 695a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern 696a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern qh_completions(ehci, qh); 697a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern 698a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern /* reschedule QH iff another request is queued */ 699a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern if (!list_empty(&qh->qtd_list) && 700e8799906045302776b35b66b16495c575db3b69cAlan Stern ehci->rh_state == EHCI_RH_RUNNING) { 701a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern rc = qh_schedule(ehci, qh); 702a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern 703a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern /* An error here likely indicates handshake failure 704a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern * or no space left in the schedule. Neither fault 705a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern * should happen often ... 706a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern * 707a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern * FIXME kill the now-dysfunctional queued urbs 708a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern */ 709a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern if (rc != 0) 710a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern ehci_err(ehci, "can't reschedule qh %p, err %d\n", 711a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern qh, rc); 712a448c9d8c58ff7d3f8cc2a8f835065460099b22dAlan Stern } 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int check_period ( 71853bd6a601a87bb6d0df844872bc15fd4e8d127ceDavid Brownell struct ehci_hcd *ehci, 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned frame, 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned uframe, 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned period, 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned usecs 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) { 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int claimed; 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* complete split running into next frame? 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * given FSTN support, we could sometimes check... 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (uframe >= 8) 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 732cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov /* convert "usecs we need" to "max already claimed" */ 733cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov usecs = ehci->uframe_periodic_max - usecs; 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* we "know" 2 and 4 uframe intervals were rejected; so 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for period 0, check _every_ microframe in the schedule. 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely (period == 0)) { 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (uframe = 0; uframe < 7; uframe++) { 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds claimed = periodic_usecs (ehci, frame, uframe); 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (claimed > usecs) 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while ((frame += 1) < ehci->periodic_size); 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* just check the specified uframe, at that period */ 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds claimed = periodic_usecs (ehci, frame, uframe); 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (claimed > usecs) 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while ((frame += period) < ehci->periodic_size); 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // success! 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int check_intr_schedule ( 76153bd6a601a87bb6d0df844872bc15fd4e8d127ceDavid Brownell struct ehci_hcd *ehci, 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned frame, 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned uframe, 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct ehci_qh *qh, 7656dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese __hc32 *c_maskp 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 76853bd6a601a87bb6d0df844872bc15fd4e8d127ceDavid Brownell int retval = -ENOSPC; 769ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman u8 mask = 0; 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!check_period (ehci, frame, uframe, qh->period, qh->usecs)) 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!qh->c_usecs) { 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *c_maskp = 0; 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 782ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman#ifdef CONFIG_USB_EHCI_TT_NEWSCHED 783ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman if (tt_available (ehci, qh->period, qh->dev, frame, uframe, 784ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman qh->tt_usecs)) { 785ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman unsigned i; 786ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 787ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman /* TODO : this may need FSTN for SSPLIT in uframe 5. */ 788ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman for (i=uframe+1; i<8 && i<uframe+4; i++) 789ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman if (!check_period (ehci, frame, i, 790ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman qh->period, qh->c_usecs)) 791ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman goto done; 792ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman else 793ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman mask |= 1 << i; 794ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 795ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman retval = 0; 796ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman 7976dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese *c_maskp = cpu_to_hc32(ehci, mask << 8); 798ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman } 799ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman#else 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Make sure this tt's buffer is also available for CSPLITs. 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We pessimize a bit; probably the typical full speed case 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doesn't need the second CSPLIT. 80353bd6a601a87bb6d0df844872bc15fd4e8d127ceDavid Brownell * 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE: both SPLIT and CSPLIT could be checked in just 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * one smart pass... 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = 0x03 << (uframe + qh->gap_uf); 8086dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese *c_maskp = cpu_to_hc32(ehci, mask << 8); 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= 1 << uframe; 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tt_no_collision (ehci, qh->period, qh->dev, frame, mask)) { 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!check_period (ehci, frame, uframe + qh->gap_uf + 1, 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh->period, qh->c_usecs)) 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!check_period (ehci, frame, uframe + qh->gap_uf, 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh->period, qh->c_usecs)) 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 820ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman#endif 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdone: 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* "first fit" scheduling policy used the first time through, 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or when the previous schedule slot can't be re-used. 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8286dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roesestatic int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh) 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 83053bd6a601a87bb6d0df844872bc15fd4e8d127ceDavid Brownell int status; 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned uframe; 8326dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese __hc32 c_mask; 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ 8343807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du struct ehci_qh_hw *hw = qh->hw; 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh_refresh(ehci, qh); 8373807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du hw->hw_next = EHCI_LIST_END(ehci); 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frame = qh->start; 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reuse the previous schedule slots, if we can */ 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (frame < qh->period) { 8423807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du uframe = ffs(hc32_to_cpup(ehci, &hw->hw_info2) & QH_SMASK); 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = check_intr_schedule (ehci, frame, --uframe, 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh, &c_mask); 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uframe = 0; 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c_mask = 0; 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = -ENOSPC; 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* else scan the schedule to find a group of slots such that all 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * uframes have enough periodic bandwidth available. 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status) { 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* "normal" case, uframing flexible except with splits */ 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (qh->period) { 85768335e816a92411649955a9903b1f30c388ea322Alan Stern int i; 85868335e816a92411649955a9903b1f30c388ea322Alan Stern 85968335e816a92411649955a9903b1f30c388ea322Alan Stern for (i = qh->period; status && i > 0; --i) { 86068335e816a92411649955a9903b1f30c388ea322Alan Stern frame = ++ehci->random_frame % qh->period; 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (uframe = 0; uframe < 8; uframe++) { 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = check_intr_schedule (ehci, 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frame, uframe, qh, 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &c_mask); 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status == 0) 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 86868335e816a92411649955a9903b1f30c388ea322Alan Stern } 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* qh->period == 0 means every uframe */ 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frame = 0; 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = check_intr_schedule (ehci, 0, 0, qh, &c_mask); 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status) 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh->start = frame; 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reset S-frame and (maybe) C-frame masks */ 8803807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du hw->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK)); 8813807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du hw->hw_info2 |= qh->period 8826dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese ? cpu_to_hc32(ehci, 1 << uframe) 8836dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese : cpu_to_hc32(ehci, QH_SMASK); 8843807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du hw->hw_info2 |= c_mask; 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_dbg (ehci, "reused qh %p schedule\n", qh); 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stuff into the periodic schedule */ 88953bd6a601a87bb6d0df844872bc15fd4e8d127ceDavid Brownell status = qh_link_periodic (ehci, qh); 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdone: 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return status; 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int intr_submit ( 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_hcd *ehci, 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct urb *urb, 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct list_head *qtd_list, 89855016f10e31bb15b85d8c500f979dfdceb37d548Al Viro gfp_t mem_flags 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) { 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned epnum; 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_qh *qh; 903e9df41c5c5899259541dc928872cad4d07b82076Alan Stern int status; 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct list_head empty; 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get endpoint and transfer/schedule data */ 907e9df41c5c5899259541dc928872cad4d07b82076Alan Stern epnum = urb->ep->desc.bEndpointAddress; 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&ehci->lock, flags); 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 911541c7d432f76771079e7c295d596ea47cc6a3030Alan Stern if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { 9128de98402652c01839ae321be6cb3054cf5735d83Benjamin Herrenschmidt status = -ESHUTDOWN; 913e9df41c5c5899259541dc928872cad4d07b82076Alan Stern goto done_not_linked; 9148de98402652c01839ae321be6cb3054cf5735d83Benjamin Herrenschmidt } 915e9df41c5c5899259541dc928872cad4d07b82076Alan Stern status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); 916e9df41c5c5899259541dc928872cad4d07b82076Alan Stern if (unlikely(status)) 917e9df41c5c5899259541dc928872cad4d07b82076Alan Stern goto done_not_linked; 9188de98402652c01839ae321be6cb3054cf5735d83Benjamin Herrenschmidt 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get qh and force any scheduling errors */ 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD (&empty); 921e9df41c5c5899259541dc928872cad4d07b82076Alan Stern qh = qh_append_tds(ehci, urb, &empty, epnum, &urb->ep->hcpriv); 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (qh == NULL) { 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = -ENOMEM; 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (qh->qh_state == QH_STATE_IDLE) { 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((status = qh_schedule (ehci, qh)) != 0) 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* then queue the urb's tds to the qh */ 932e9df41c5c5899259541dc928872cad4d07b82076Alan Stern qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv); 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_ON (qh == NULL); 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ... update usbfs periodic stats */ 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_to_hcd(ehci)->self.bandwidth_int_reqs++; 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdone: 939e9df41c5c5899259541dc928872cad4d07b82076Alan Stern if (unlikely(status)) 940e9df41c5c5899259541dc928872cad4d07b82076Alan Stern usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); 941e9df41c5c5899259541dc928872cad4d07b82076Alan Sterndone_not_linked: 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&ehci->lock, flags); 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status) 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qtd_list_free (ehci, urb, qtd_list); 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return status; 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ehci_iso_stream ops work with both ITD and SITD */ 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct ehci_iso_stream * 95455016f10e31bb15b85d8c500f979dfdceb37d548Al Viroiso_stream_alloc (gfp_t mem_flags) 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream; 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9587b842b6e3704f4b9606ff8a4ffe03579d9addf5ePekka Enberg stream = kzalloc(sizeof *stream, mem_flags); 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely (stream != NULL)) { 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&stream->td_list); 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&stream->free_list); 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->next_uframe = -1; 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->refcount = 1; 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return stream; 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsiso_stream_init ( 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_hcd *ehci, 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream, 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_device *dev, 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int pipe, 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned interval 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static const u8 smask_out [] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f }; 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 buf1; 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned epnum, maxp; 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int is_input; 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long bandwidth; 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this might be a "high bandwidth" highspeed endpoint, 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as encoded in the ep descriptor's wMaxPacket field 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epnum = usb_pipeendpoint (pipe); 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds is_input = usb_pipein (pipe) ? USB_DIR_IN : 0; 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maxp = usb_maxpacket(dev, pipe, !is_input); 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (is_input) { 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf1 = (1 << 11); 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf1 = 0; 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* knows about ITD vs SITD */ 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->speed == USB_SPEED_HIGH) { 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned multi = hb_mult(maxp); 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->highspeed = 1; 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maxp = max_packet(maxp); 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf1 |= maxp; 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds maxp *= multi; 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10076dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese stream->buf0 = cpu_to_hc32(ehci, (epnum << 8) | dev->devnum); 10086dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese stream->buf1 = cpu_to_hc32(ehci, buf1); 10096dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese stream->buf2 = cpu_to_hc32(ehci, multi); 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* usbfs wants to report the average usecs per frame tied up 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * when transfers on this endpoint are scheduled ... 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->usecs = HS_USECS_ISO (maxp); 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bandwidth = stream->usecs * 8; 1016372dd6e8ed924e876f3beb598721e813ad7fa323Alan Stern bandwidth /= interval; 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 addr; 1020d0384200f6b608e77fb5ddf7dfae1bf0e42c1c6eDavid Brownell int think_time; 1021469d02293d494d30dba81895cd3d34b0a3a6d51aClemens Ladisch int hs_transfers; 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = dev->ttport << 24; 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ehci_is_TDI(ehci) 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || (dev->tt->hub != 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_to_hcd(ehci)->self.root_hub)) 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr |= dev->tt->hub->devnum << 16; 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr |= epnum << 8; 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr |= dev->devnum; 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->usecs = HS_USECS_ISO (maxp); 1031d0384200f6b608e77fb5ddf7dfae1bf0e42c1c6eDavid Brownell think_time = dev->tt ? dev->tt->think_time : 0; 1032d0384200f6b608e77fb5ddf7dfae1bf0e42c1c6eDavid Brownell stream->tt_usecs = NS_TO_US (think_time + usb_calc_bus_time ( 1033d0384200f6b608e77fb5ddf7dfae1bf0e42c1c6eDavid Brownell dev->speed, is_input, 1, maxp)); 1034469d02293d494d30dba81895cd3d34b0a3a6d51aClemens Ladisch hs_transfers = max (1u, (maxp + 187) / 188); 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (is_input) { 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 tmp; 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr |= 1 << 31; 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->c_usecs = stream->usecs; 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->usecs = HS_USECS_ISO (1); 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->raw_mask = 1; 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1043469d02293d494d30dba81895cd3d34b0a3a6d51aClemens Ladisch /* c-mask as specified in USB 2.0 11.18.4 3.c */ 1044469d02293d494d30dba81895cd3d34b0a3a6d51aClemens Ladisch tmp = (1 << (hs_transfers + 2)) - 1; 1045469d02293d494d30dba81895cd3d34b0a3a6d51aClemens Ladisch stream->raw_mask |= tmp << (8 + 2); 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 1047469d02293d494d30dba81895cd3d34b0a3a6d51aClemens Ladisch stream->raw_mask = smask_out [hs_transfers - 1]; 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bandwidth = stream->usecs + stream->c_usecs; 1049372dd6e8ed924e876f3beb598721e813ad7fa323Alan Stern bandwidth /= interval << 3; 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stream->splits gets created from raw_mask later */ 10526dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese stream->address = cpu_to_hc32(ehci, addr); 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->bandwidth = bandwidth; 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->udev = dev; 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->bEndpointAddress = is_input | epnum; 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->interval = interval; 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->maxp = maxp; 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsiso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream) 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->refcount--; 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* free whenever just a dev->ep reference remains. 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * not like a QH -- no persistent state (toggle, halt) 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (stream->refcount == 1) { 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // BUG_ON (!list_empty(&stream->td_list)); 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (!list_empty (&stream->free_list)) { 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct list_head *entry; 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = stream->free_list.next; 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del (entry); 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* knows about ITD vs SITD */ 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (stream->highspeed) { 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_itd *itd; 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd = list_entry (entry, struct ehci_itd, 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd_list); 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_pool_free (ehci->itd_pool, itd, 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd->itd_dma); 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_sitd *sitd; 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd = list_entry (entry, struct ehci_sitd, 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd_list); 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_pool_free (ehci->sitd_pool, sitd, 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd->sitd_dma); 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->bEndpointAddress &= 0x0f; 10999aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese if (stream->ep) 11009aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese stream->ep->hcpriv = NULL; 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(stream); 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline struct ehci_iso_stream * 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsiso_stream_get (struct ehci_iso_stream *stream) 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely (stream != NULL)) 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->refcount++; 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return stream; 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct ehci_iso_stream * 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsiso_stream_find (struct ehci_hcd *ehci, struct urb *urb) 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned epnum; 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream; 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_host_endpoint *ep; 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds epnum = usb_pipeendpoint (urb->pipe); 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (usb_pipein(urb->pipe)) 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ep = urb->dev->ep_in[epnum]; 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ep = urb->dev->ep_out[epnum]; 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&ehci->lock, flags); 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream = ep->hcpriv; 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely (stream == NULL)) { 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream = iso_stream_alloc(GFP_ATOMIC); 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely (stream != NULL)) { 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* dev->ep owns the initial refcount */ 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ep->hcpriv = stream; 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->ep = ep; 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iso_stream_init(ehci, stream, urb->dev, urb->pipe, 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->interval); 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11411082f57abfa26590b60c43f503afb24102a37016Clemens Ladisch /* if dev->ep [epnum] is a QH, hw is set */ 11421082f57abfa26590b60c43f503afb24102a37016Clemens Ladisch } else if (unlikely (stream->hw != NULL)) { 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n", 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->dev->devpath, epnum, 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_pipein(urb->pipe) ? "in" : "out"); 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream = NULL; 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* caller guarantees an eventual matching iso_stream_put */ 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream = iso_stream_get (stream); 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&ehci->lock, flags); 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return stream; 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ehci_iso_sched ops can be ITD-only or SITD-only */ 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct ehci_iso_sched * 116155016f10e31bb15b85d8c500f979dfdceb37d548Al Viroiso_sched_alloc (unsigned packets, gfp_t mem_flags) 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_sched *iso_sched; 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int size = sizeof *iso_sched; 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size += packets * sizeof (struct ehci_iso_packet); 116780b6ca48321974a6566a1c9048ba34f60420bca6Eric Sesterhenn iso_sched = kzalloc(size, mem_flags); 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely (iso_sched != NULL)) { 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD (&iso_sched->td_list); 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return iso_sched; 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void 11756dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roeseitd_sched_init( 11766dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese struct ehci_hcd *ehci, 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_sched *iso_sched, 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream, 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct urb *urb 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned i; 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t dma = urb->transfer_dma; 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* how many uframes are needed for these transfers */ 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iso_sched->span = urb->number_of_packets * stream->interval; 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* figure out per-uframe itd fields that we'll need later 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * when we fit new itds into the schedule. 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < urb->number_of_packets; i++) { 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_packet *uframe = &iso_sched->packet [i]; 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned length; 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t buf; 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 trans; 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds length = urb->iso_frame_desc [i].length; 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf = dma + urb->iso_frame_desc [i].offset; 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds trans = EHCI_ISOC_ACTIVE; 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds trans |= buf & 0x0fff; 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely (((i + 1) == urb->number_of_packets)) 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && !(urb->transfer_flags & URB_NO_INTERRUPT)) 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds trans |= EHCI_ITD_IOC; 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds trans |= length << 16; 12066dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese uframe->transaction = cpu_to_hc32(ehci, trans); 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 120877078570abe0848c3076b4f7d42f79b1407f3e8fDavid Brownell /* might need to cross a buffer page within a uframe */ 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uframe->bufp = (buf & ~(u64)0x0fff); 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf += length; 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff)))) 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uframe->cross = 1; 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsiso_sched_free ( 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream, 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_sched *iso_sched 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!iso_sched) 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // caller must hold ehci->lock! 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_splice (&iso_sched->td_list, &stream->free_list); 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree (iso_sched); 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsitd_urb_transaction ( 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream, 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_hcd *ehci, 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct urb *urb, 123455016f10e31bb15b85d8c500f979dfdceb37d548Al Viro gfp_t mem_flags 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_itd *itd; 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t itd_dma; 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned num_itds; 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_sched *sched; 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sched = iso_sched_alloc (urb->number_of_packets, mem_flags); 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely (sched == NULL)) 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12486dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese itd_sched_init(ehci, sched, stream, urb); 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (urb->interval < 8) 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_itds = 1 + (sched->span + 7) / 8; 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_itds = urb->number_of_packets; 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* allocate/init ITDs */ 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&ehci->lock, flags); 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < num_itds; i++) { 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* free_list.next might be cache-hot ... but maybe 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the HC caches it too. avoid that issue for now. 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* prefer previously-allocated itds */ 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely (!list_empty(&stream->free_list))) { 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd = list_entry (stream->free_list.prev, 12666dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese struct ehci_itd, itd_list); 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del (&itd->itd_list); 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd_dma = itd->itd_dma; 12693d01f0fe6b66dd34511eaf35e06764b8997187bcKarsten Wiese } else { 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&ehci->lock, flags); 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd = dma_pool_alloc (ehci->itd_pool, mem_flags, 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &itd_dma); 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&ehci->lock, flags); 12743d01f0fe6b66dd34511eaf35e06764b8997187bcKarsten Wiese if (!itd) { 12753d01f0fe6b66dd34511eaf35e06764b8997187bcKarsten Wiese iso_sched_free(stream, sched); 12763d01f0fe6b66dd34511eaf35e06764b8997187bcKarsten Wiese spin_unlock_irqrestore(&ehci->lock, flags); 12773d01f0fe6b66dd34511eaf35e06764b8997187bcKarsten Wiese return -ENOMEM; 12783d01f0fe6b66dd34511eaf35e06764b8997187bcKarsten Wiese } 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset (itd, 0, sizeof *itd); 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd->itd_dma = itd_dma; 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add (&itd->itd_list, &sched->td_list); 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&ehci->lock, flags); 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* temporarily store schedule info in hcpriv */ 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->hcpriv = sched; 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->error_count = 0; 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsitd_slot_ok ( 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_hcd *ehci, 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 mod, 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 uframe, 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 usecs, 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 period 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uframe %= period; 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 1306cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov /* can't commit more than uframe_periodic_max usec */ 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7) 1308cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov > (ehci->uframe_periodic_max - usecs)) 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* we know urb->interval is 2^N uframes */ 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uframe += period; 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (uframe < mod); 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssitd_slot_ok ( 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_hcd *ehci, 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 mod, 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream, 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 uframe, 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_sched *sched, 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 period_uframes 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 mask, tmp; 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 frame, uf; 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = stream->raw_mask << (uframe & 7); 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* for IN, don't wrap CSPLIT into the next frame */ 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mask & ~0xffff) 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this multi-pass logic is simple, but performance may 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * suffer when the schedule data isn't cached. 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check bandwidth */ 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uframe %= period_uframes; 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 max_used; 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frame = uframe >> 3; 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uf = uframe & 7; 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1348ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman#ifdef CONFIG_USB_EHCI_TT_NEWSCHED 1349ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman /* The tt's fullspeed bus bandwidth must be available. 1350ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman * tt_available scheduling guarantees 10+% for control/bulk. 1351ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman */ 1352ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman if (!tt_available (ehci, period_uframes << 3, 1353ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman stream->udev, frame, uf, stream->tt_usecs)) 1354ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman return 0; 1355ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman#else 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* tt must be idle for start(s), any gap, and csplit. 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * assume scheduling slop leaves 10+% for control/bulk. 13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!tt_no_collision (ehci, period_uframes << 3, 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->udev, frame, mask)) 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1362ba47f66bd9fc451e9ce88f291e057b2f4910d01cDan Streetman#endif 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check starts (OUT uses more than one) */ 1365cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov max_used = ehci->uframe_periodic_max - stream->usecs; 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) { 13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (periodic_usecs (ehci, frame, uf) > max_used) 13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* for IN, check CSPLIT */ 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (stream->c_usecs) { 13730c7346229c48fa899a1837d9200894701ea81dacClemens Ladisch uf = uframe & 7; 1374cc62a7eb6396e8be95b9a30053ed09191818b99bKirill Smelkov max_used = ehci->uframe_periodic_max - stream->c_usecs; 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = 1 << uf; 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp <<= 8; 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((stream->raw_mask & tmp) == 0) 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (periodic_usecs (ehci, frame, uf) 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds > max_used) 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (++uf < 8); 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* we know urb->interval is 2^N uframes */ 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uframe += period_uframes; 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (uframe < mod); 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13906dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese stream->splits = cpu_to_hc32(ehci, stream->raw_mask << (uframe & 7)); 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This scheduler plans almost as far into the future as it has actual 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * periodic schedule slots. (Affected by TUNE_FLS, which defaults to 13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "as small as possible" to be cache-friendlier.) That limits the size 13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transfers you can stream reliably; avoid more than 64 msec per urb. 13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Also avoid queue depths of less than ehci's worst irq latency (affected 14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by the per-urb URB_NO_INTERRUPT hint, the log2_irq_thresh module parameter, 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and other factors); or more than about 230 msec total (for portability, 14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * given EHCI_TUNE_FLS and the slop). Or, write a smarter scheduler! 14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1405d7e055f1975cac560427c924d2bff4b5d41fe442Sarah Sharp#define SCHEDULE_SLOP 80 /* microframes */ 14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsiso_stream_schedule ( 14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_hcd *ehci, 14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct urb *urb, 14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream 14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1414ffda080353979273e8aa69fc1e6134f20643ae56Alan Stern u32 now, next, start, period, span; 14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status; 14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned mod = ehci->periodic_size << 3; 14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_sched *sched = urb->hcpriv; 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1419ffda080353979273e8aa69fc1e6134f20643ae56Alan Stern period = urb->interval; 1420ffda080353979273e8aa69fc1e6134f20643ae56Alan Stern span = sched->span; 1421ffda080353979273e8aa69fc1e6134f20643ae56Alan Stern if (!stream->highspeed) { 1422ffda080353979273e8aa69fc1e6134f20643ae56Alan Stern period <<= 3; 1423ffda080353979273e8aa69fc1e6134f20643ae56Alan Stern span <<= 3; 1424ffda080353979273e8aa69fc1e6134f20643ae56Alan Stern } 1425ffda080353979273e8aa69fc1e6134f20643ae56Alan Stern 1426ffda080353979273e8aa69fc1e6134f20643ae56Alan Stern if (span > mod - SCHEDULE_SLOP) { 14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_dbg (ehci, "iso request %p too long\n", urb); 14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = -EFBIG; 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 143268aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern now = ehci_read_frame_index(ehci) & (mod - 1); 14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1434b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern /* Typical case: reuse current schedule, stream is still active. 1435b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern * Hopefully there are no gaps from the host falling behind 1436b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern * (irq delays etc), but if there are we'll take the next 1437b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern * slot in the schedule, implicitly assuming URB_ISO_ASAP. 14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely (!list_empty (&stream->td_list))) { 14401fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern u32 excess; 1441dccd574cccad950d9ed9bc192eae4089c6044d9dSarah Sharp 1442dccd574cccad950d9ed9bc192eae4089c6044d9dSarah Sharp /* For high speed devices, allow scheduling within the 1443ae68a83bdc1971cb02fefc7a686ba6d077065e71Alan Stern * isochronous scheduling threshold. For full speed devices 1444ae68a83bdc1971cb02fefc7a686ba6d077065e71Alan Stern * and Intel PCI-based controllers, don't (work around for 1445ae68a83bdc1971cb02fefc7a686ba6d077065e71Alan Stern * Intel ICH9 bug). 1446dccd574cccad950d9ed9bc192eae4089c6044d9dSarah Sharp */ 1447ae68a83bdc1971cb02fefc7a686ba6d077065e71Alan Stern if (!stream->highspeed && ehci->fs_i_thresh) 1448dccd574cccad950d9ed9bc192eae4089c6044d9dSarah Sharp next = now + ehci->i_thresh; 1449dccd574cccad950d9ed9bc192eae4089c6044d9dSarah Sharp else 1450dccd574cccad950d9ed9bc192eae4089c6044d9dSarah Sharp next = now; 1451b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern 14521fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern /* Fell behind (by up to twice the slop amount)? 14531fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern * We decide based on the time of the last currently-scheduled 14541fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern * slot, not the time of the next available slot. 14551fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern */ 14561fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern excess = (stream->next_uframe - period - next) & (mod - 1); 14571fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern if (excess >= mod - 2 * SCHEDULE_SLOP) 14581fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern start = next + excess - mod + period * 14591fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern DIV_ROUND_UP(mod - excess, period); 14601fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern else 14611fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern start = next + excess + period; 14621fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern if (start - now >= mod) { 14631fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n", 14641fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern urb, start - now - period, period, 14651fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern mod); 1466b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern status = -EFBIG; 1467b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern goto fail; 1468b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern } 14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* need to schedule; when's the next (u)frame we could start? 14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this is bigger than ehci->i_thresh allows; scheduling itself 14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * isn't free, the slop should handle reasonably slow cpus. it 14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can also help high bandwidth if the dma and irq loads don't 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * jump until after the queue is primed. 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14771fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern else { 1478e3420901eba65b1c46bed86d360e3a8685d20734Matthieu CASTET int done = 0; 14791fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern start = SCHEDULE_SLOP + (now & ~0x07); 14801fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern 14811fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ 14821fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern 1483811c926c538f7e8d3c08b630dd5844efd7e000f6Thomas Poussevin /* find a uframe slot with enough bandwidth. 1484811c926c538f7e8d3c08b630dd5844efd7e000f6Thomas Poussevin * Early uframes are more precious because full-speed 1485811c926c538f7e8d3c08b630dd5844efd7e000f6Thomas Poussevin * iso IN transfers can't use late uframes, 1486811c926c538f7e8d3c08b630dd5844efd7e000f6Thomas Poussevin * and therefore they should be allocated last. 1487811c926c538f7e8d3c08b630dd5844efd7e000f6Thomas Poussevin */ 1488811c926c538f7e8d3c08b630dd5844efd7e000f6Thomas Poussevin next = start; 1489811c926c538f7e8d3c08b630dd5844efd7e000f6Thomas Poussevin start += period; 1490811c926c538f7e8d3c08b630dd5844efd7e000f6Thomas Poussevin do { 1491811c926c538f7e8d3c08b630dd5844efd7e000f6Thomas Poussevin start--; 14921fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern /* check schedule: enough space? */ 14931fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern if (stream->highspeed) { 14941fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern if (itd_slot_ok(ehci, mod, start, 14951fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern stream->usecs, period)) 1496e3420901eba65b1c46bed86d360e3a8685d20734Matthieu CASTET done = 1; 14971fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern } else { 14981fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern if ((start % 8) >= 6) 14991fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern continue; 15001fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern if (sitd_slot_ok(ehci, mod, stream, 15011fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern start, sched, period)) 1502e3420901eba65b1c46bed86d360e3a8685d20734Matthieu CASTET done = 1; 15031fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern } 1504e3420901eba65b1c46bed86d360e3a8685d20734Matthieu CASTET } while (start > next && !done); 15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15061fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern /* no room in the schedule */ 1507e3420901eba65b1c46bed86d360e3a8685d20734Matthieu CASTET if (!done) { 15081fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n", 15091fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern urb, now, now + mod); 15101fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern status = -ENOSPC; 15111fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern goto fail; 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15151fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern /* Tried to schedule too far into the future? */ 15161fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern if (unlikely(start - now + span - period 15171fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern >= mod - 2 * SCHEDULE_SLOP)) { 15181fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n", 15191fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern urb, start - now, span - period, 15201fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern mod - 2 * SCHEDULE_SLOP); 15211fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern status = -EFBIG; 15221fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern goto fail; 15231fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern } 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15251fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern stream->next_uframe = start & (mod - 1); 15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* report high speed start in uframes; full speed, in frames */ 15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->start_frame = stream->next_uframe; 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!stream->highspeed) 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->start_frame >>= 3; 15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 15321fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern 15331fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern fail: 15341fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern iso_sched_free(stream, sched); 15351fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern urb->hcpriv = NULL; 15361fb2e0558781b07d2ecaabf94c81c17ac820d8f0Alan Stern return status; 15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void 15426dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roeseitd_init(struct ehci_hcd *ehci, struct ehci_iso_stream *stream, 15436dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese struct ehci_itd *itd) 15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 154777078570abe0848c3076b4f7d42f79b1407f3e8fDavid Brownell /* it's been recently zeroed */ 15486dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese itd->hw_next = EHCI_LIST_END(ehci); 15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd->hw_bufp [0] = stream->buf0; 15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd->hw_bufp [1] = stream->buf1; 15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd->hw_bufp [2] = stream->buf2; 15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 8; i++) 15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd->index[i] = -1; 15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* All other fields are filled when scheduling */ 15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void 15606dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roeseitd_patch( 15616dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese struct ehci_hcd *ehci, 15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_itd *itd, 15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_sched *iso_sched, 15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned index, 156577078570abe0848c3076b4f7d42f79b1407f3e8fDavid Brownell u16 uframe 15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_packet *uf = &iso_sched->packet [index]; 15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned pg = itd->pg; 15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // BUG_ON (pg == 6 && uf->cross); 15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uframe &= 0x07; 15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd->index [uframe] = index; 15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15766dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese itd->hw_transaction[uframe] = uf->transaction; 15776dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese itd->hw_transaction[uframe] |= cpu_to_hc32(ehci, pg << 12); 15786dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese itd->hw_bufp[pg] |= cpu_to_hc32(ehci, uf->bufp & ~(u32)0); 15796dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(uf->bufp >> 32)); 15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* iso_frame_desc[].offset must be strictly increasing */ 158277078570abe0848c3076b4f7d42f79b1407f3e8fDavid Brownell if (unlikely (uf->cross)) { 15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u64 bufp = uf->bufp + 4096; 15846dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese 15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd->pg = ++pg; 15866dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese itd->hw_bufp[pg] |= cpu_to_hc32(ehci, bufp & ~(u32)0); 15876dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(bufp >> 32)); 15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void 15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) 15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 159492bc3648e6027384479852b770a542722fadee7cClemens Ladisch union ehci_shadow *prev = &ehci->pshadow[frame]; 159592bc3648e6027384479852b770a542722fadee7cClemens Ladisch __hc32 *hw_p = &ehci->periodic[frame]; 159692bc3648e6027384479852b770a542722fadee7cClemens Ladisch union ehci_shadow here = *prev; 159792bc3648e6027384479852b770a542722fadee7cClemens Ladisch __hc32 type = 0; 159892bc3648e6027384479852b770a542722fadee7cClemens Ladisch 159992bc3648e6027384479852b770a542722fadee7cClemens Ladisch /* skip any iso nodes which might belong to previous microframes */ 160092bc3648e6027384479852b770a542722fadee7cClemens Ladisch while (here.ptr) { 160192bc3648e6027384479852b770a542722fadee7cClemens Ladisch type = Q_NEXT_TYPE(ehci, *hw_p); 160292bc3648e6027384479852b770a542722fadee7cClemens Ladisch if (type == cpu_to_hc32(ehci, Q_TYPE_QH)) 160392bc3648e6027384479852b770a542722fadee7cClemens Ladisch break; 160492bc3648e6027384479852b770a542722fadee7cClemens Ladisch prev = periodic_next_shadow(ehci, prev, type); 160592bc3648e6027384479852b770a542722fadee7cClemens Ladisch hw_p = shadow_next_periodic(ehci, &here, type); 160692bc3648e6027384479852b770a542722fadee7cClemens Ladisch here = *prev; 160792bc3648e6027384479852b770a542722fadee7cClemens Ladisch } 160892bc3648e6027384479852b770a542722fadee7cClemens Ladisch 160992bc3648e6027384479852b770a542722fadee7cClemens Ladisch itd->itd_next = here; 161092bc3648e6027384479852b770a542722fadee7cClemens Ladisch itd->hw_next = *hw_p; 161192bc3648e6027384479852b770a542722fadee7cClemens Ladisch prev->itd = itd; 16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd->frame = frame; 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb (); 161492bc3648e6027384479852b770a542722fadee7cClemens Ladisch *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); 16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* fit urb's itds into the selected schedule slot; activate as needed */ 16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsitd_link_urb ( 16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_hcd *ehci, 16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct urb *urb, 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned mod, 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream 16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 162677078570abe0848c3076b4f7d42f79b1407f3e8fDavid Brownell int packet; 16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned next_uframe, uframe, frame; 16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_sched *iso_sched = urb->hcpriv; 16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_itd *itd; 16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631bccbefaae050186bed3bcc74b1fd1a9b8c6710b2Alan Stern next_uframe = stream->next_uframe & (mod - 1); 16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely (list_empty(&stream->td_list))) { 16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_to_hcd(ehci)->self.bandwidth_allocated 16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds += stream->bandwidth; 16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_vdbg (ehci, 16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "schedule devp %s ep%d%s-iso period %d start %d.%d\n", 16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->dev->devpath, stream->bEndpointAddress & 0x0f, 16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", 16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->interval, 16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_uframe >> 3, next_uframe & 0x7); 16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 164305570297ecbe834b1756b522412b68eaffb9ab11Alex He 164405570297ecbe834b1756b522412b68eaffb9ab11Alex He if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { 1645ad93562bdeecdded7d02eaaaf1aa5705ab57b1b7Andiry Xu if (ehci->amd_pll_fix == 1) 1646ad93562bdeecdded7d02eaaaf1aa5705ab57b1b7Andiry Xu usb_amd_quirk_pll_disable(); 164705570297ecbe834b1756b522412b68eaffb9ab11Alex He } 164805570297ecbe834b1756b522412b68eaffb9ab11Alex He 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* fill iTDs uframe by uframe */ 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (packet = 0, itd = NULL; packet < urb->number_of_packets; ) { 16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (itd == NULL) { 16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ASSERT: we have all necessary itds */ 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // BUG_ON (list_empty (&iso_sched->td_list)); 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ASSERT: no itds for this endpoint in this uframe */ 16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd = list_entry (iso_sched->td_list.next, 16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_itd, itd_list); 16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_move_tail (&itd->itd_list, &stream->td_list); 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd->stream = iso_stream_get (stream); 1663508db8c954d55ed30f870d2c24d741ba6269d13cKarsten Wiese itd->urb = urb; 16646dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese itd_init (ehci, stream, itd); 16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uframe = next_uframe & 0x07; 16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frame = next_uframe >> 3; 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16706dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese itd_patch(ehci, itd, iso_sched, packet, uframe); 16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_uframe += stream->interval; 1673bccbefaae050186bed3bcc74b1fd1a9b8c6710b2Alan Stern next_uframe &= mod - 1; 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds packet++; 16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* link completed itds into the schedule */ 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((next_uframe >> 3) != frame) 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds || packet == urb->number_of_packets) { 1679bccbefaae050186bed3bcc74b1fd1a9b8c6710b2Alan Stern itd_link(ehci, frame & (ehci->periodic_size - 1), itd); 16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd = NULL; 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->next_uframe = next_uframe; 16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't need that schedule data any more */ 16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iso_sched_free (stream, iso_sched); 16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->hcpriv = NULL; 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timer_action (ehci, TIMER_IO_WATCHDOG); 169001c17142659c02d8cd4c67acdd8358180c5c4fb6David Brownell return enable_periodic(ehci); 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR) 16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 169530bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell/* Process and recycle a completed ITD. Return true iff its urb completed, 169630bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * and hence its completion callback probably added things to the hardware 169730bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * schedule. 169830bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * 169930bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * Note that we carefully avoid recycling this descriptor until after any 170030bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * completion callback runs, so that it won't be reused quickly. That is, 170130bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * assuming (a) no more than two urbs per frame on this endpoint, and also 170230bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * (b) only this endpoint's completions submit URBs. It seems some silicon 170330bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * corrupts things if you reuse completed descriptors very quickly... 170430bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell */ 17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned 17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsitd_complete ( 17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_hcd *ehci, 17087d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells struct ehci_itd *itd 17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) { 17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct urb *urb = itd->urb; 17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_iso_packet_descriptor *desc; 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 t; 17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned uframe; 17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int urb_index = -1; 17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream = itd->stream; 17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_device *dev; 171730bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell unsigned retval = false; 17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* for each uframe with a packet */ 17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (uframe = 0; uframe < 8; uframe++) { 17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely (itd->index[uframe] == -1)) 17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb_index = itd->index[uframe]; 17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds desc = &urb->iso_frame_desc [urb_index]; 17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17266dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]); 17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd->hw_transaction [uframe] = 0; 17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* report transfer status */ 17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely (t & ISO_ERRS)) { 17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->error_count++; 17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (t & EHCI_ISOC_BUF_ERR) 17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds desc->status = usb_pipein (urb->pipe) 17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ? -ENOSR /* hc couldn't read */ 17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : -ECOMM; /* hc couldn't write */ 17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (t & EHCI_ISOC_BABBLE) 17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds desc->status = -EOVERFLOW; 17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else /* (t & EHCI_ISOC_XACTERR) */ 17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds desc->status = -EPROTO; 17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* HC need not update length with this error */ 1742ec6d67e39f5638c792eb7490bf32586ccb9d8005Alan Stern if (!(t & EHCI_ISOC_BABBLE)) { 1743ec6d67e39f5638c792eb7490bf32586ccb9d8005Alan Stern desc->actual_length = EHCI_ITD_LENGTH(t); 1744ec6d67e39f5638c792eb7490bf32586ccb9d8005Alan Stern urb->actual_length += desc->actual_length; 1745ec6d67e39f5638c792eb7490bf32586ccb9d8005Alan Stern } 17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) { 17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds desc->status = 0; 1748ec6d67e39f5638c792eb7490bf32586ccb9d8005Alan Stern desc->actual_length = EHCI_ITD_LENGTH(t); 1749ec6d67e39f5638c792eb7490bf32586ccb9d8005Alan Stern urb->actual_length += desc->actual_length; 1750b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern } else { 1751b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern /* URB was too late */ 1752b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern desc->status = -EXDEV; 17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* handle completion now? */ 17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely ((urb_index + 1) != urb->number_of_packets)) 175830bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell goto done; 17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ASSERT: it's really the last itd for this urb 17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry (itd, &stream->td_list, itd_list) 17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_ON (itd->urb == urb); 17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1765aa16ca307ee2da304d3a5fc0fc5e50ef8047c9e9David Brownell /* give urb back to the driver; completion often (re)submits */ 17666a8e87b23ff4a979bde5451a242466a4b3f9fe7dAlan Stern dev = urb->dev; 176714c04c0f88f228fee1f412be91d6edcb935c78aaAlan Stern ehci_urb_done(ehci, urb, 0); 176830bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell retval = true; 17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb = NULL; 177001c17142659c02d8cd4c67acdd8358180c5c4fb6David Brownell (void) disable_periodic(ehci); 17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; 17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 177305570297ecbe834b1756b522412b68eaffb9ab11Alex He if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { 1774ad93562bdeecdded7d02eaaaf1aa5705ab57b1b7Andiry Xu if (ehci->amd_pll_fix == 1) 1775ad93562bdeecdded7d02eaaaf1aa5705ab57b1b7Andiry Xu usb_amd_quirk_pll_enable(); 177605570297ecbe834b1756b522412b68eaffb9ab11Alex He } 177705570297ecbe834b1756b522412b68eaffb9ab11Alex He 1778508db8c954d55ed30f870d2c24d741ba6269d13cKarsten Wiese if (unlikely(list_is_singular(&stream->td_list))) { 17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_to_hcd(ehci)->self.bandwidth_allocated 17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -= stream->bandwidth; 17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_vdbg (ehci, 17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "deschedule devp %s ep%d%s-iso\n", 17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->devpath, stream->bEndpointAddress & 0x0f, 17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); 17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iso_stream_put (ehci, stream); 17879aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese 178830bf54e62a7926a483b4e36015bb4eb1372e6303David Brownelldone: 178930bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell itd->urb = NULL; 17909aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese if (ehci->clock_frame != itd->frame || itd->index[7] != -1) { 17919aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese /* OK to recycle this ITD now. */ 17929aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese itd->stream = NULL; 17939aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese list_move(&itd->itd_list, &stream->free_list); 17949aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese iso_stream_put(ehci, stream); 17959aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese } else { 17969aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese /* HW might remember this ITD, so we can't recycle it yet. 17979aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese * Move it to a safe place until a new frame starts. 17989aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese */ 17999aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese list_move(&itd->itd_list, &ehci->cached_itd_list); 18009aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese if (stream->refcount == 2) { 18019aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese /* If iso_stream_put() were called here, stream 18029aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese * would be freed. Instead, just prevent reuse. 18039aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese */ 18049aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese stream->ep->hcpriv = NULL; 18059aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese stream->ep = NULL; 18069aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese } 18079aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese } 180830bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell return retval; 18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18135db539e49fc7471e23bf3c94ca304f008cb7b7f3Olav Kongasstatic int itd_submit (struct ehci_hcd *ehci, struct urb *urb, 181455016f10e31bb15b85d8c500f979dfdceb37d548Al Viro gfp_t mem_flags) 18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status = -EINVAL; 18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream; 18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Get iso_stream head */ 18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream = iso_stream_find (ehci, urb); 18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely (stream == NULL)) { 18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_dbg (ehci, "can't get iso stream\n"); 18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely (urb->interval != stream->interval)) { 18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_dbg (ehci, "can't change iso interval %d --> %d\n", 18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->interval, urb->interval); 18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef EHCI_URB_TRACE 18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_dbg (ehci, 18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%p]\n", 1835441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison __func__, urb->dev->devpath, urb, 18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_pipeendpoint (urb->pipe), 18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_pipein (urb->pipe) ? "in" : "out", 18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->transfer_buffer_length, 18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->number_of_packets, urb->interval, 18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream); 18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* allocate ITDs w/o locking anything */ 18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = itd_urb_transaction (stream, ehci, urb, mem_flags); 18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely (status < 0)) { 18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_dbg (ehci, "can't init itds\n"); 18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* schedule ... need to lock */ 18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&ehci->lock, flags); 1852541c7d432f76771079e7c295d596ea47cc6a3030Alan Stern if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { 18538de98402652c01839ae321be6cb3054cf5735d83Benjamin Herrenschmidt status = -ESHUTDOWN; 1854e9df41c5c5899259541dc928872cad4d07b82076Alan Stern goto done_not_linked; 1855e9df41c5c5899259541dc928872cad4d07b82076Alan Stern } 1856e9df41c5c5899259541dc928872cad4d07b82076Alan Stern status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); 1857e9df41c5c5899259541dc928872cad4d07b82076Alan Stern if (unlikely(status)) 1858e9df41c5c5899259541dc928872cad4d07b82076Alan Stern goto done_not_linked; 1859e9df41c5c5899259541dc928872cad4d07b82076Alan Stern status = iso_stream_schedule(ehci, urb, stream); 186053bd6a601a87bb6d0df844872bc15fd4e8d127ceDavid Brownell if (likely (status == 0)) 18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); 1862e9df41c5c5899259541dc928872cad4d07b82076Alan Stern else 1863e9df41c5c5899259541dc928872cad4d07b82076Alan Stern usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); 1864e9df41c5c5899259541dc928872cad4d07b82076Alan Sterndone_not_linked: 18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&ehci->lock, flags); 18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdone: 18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely (status < 0)) 18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iso_stream_put (ehci, stream); 18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return status; 18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "Split ISO TDs" ... used for USB 1.1 devices going through the 18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * TTs in USB 2.0 hubs. These need microframe scheduling. 18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void 18816dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roesesitd_sched_init( 18826dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese struct ehci_hcd *ehci, 18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_sched *iso_sched, 18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream, 18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct urb *urb 18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned i; 18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t dma = urb->transfer_dma; 18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* how many frames are needed for these transfers */ 18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iso_sched->span = urb->number_of_packets * stream->interval; 18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* figure out per-frame sitd fields that we'll need later 18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * when we fit new sitds into the schedule. 18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < urb->number_of_packets; i++) { 18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_packet *packet = &iso_sched->packet [i]; 18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned length; 19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t buf; 19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 trans; 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds length = urb->iso_frame_desc [i].length & 0x03ff; 19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf = dma + urb->iso_frame_desc [i].offset; 19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds trans = SITD_STS_ACTIVE; 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((i + 1) == urb->number_of_packets) 19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && !(urb->transfer_flags & URB_NO_INTERRUPT)) 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds trans |= SITD_IOC; 19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds trans |= length << 16; 19116dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese packet->transaction = cpu_to_hc32(ehci, trans); 19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* might need to cross a buffer page within a td */ 19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds packet->bufp = buf; 19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds packet->buf1 = (buf + length) & ~0x0fff; 19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (packet->buf1 != (buf & ~(u64)0x0fff)) 19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds packet->cross = 1; 19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191953bd6a601a87bb6d0df844872bc15fd4e8d127ceDavid Brownell /* OUT uses multiple start-splits */ 19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (stream->bEndpointAddress & USB_DIR_IN) 19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds length = (length + 187) / 188; 19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (length > 1) /* BEGIN vs ALL */ 19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds length |= 1 << 3; 19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds packet->buf1 |= length; 19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssitd_urb_transaction ( 19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream, 19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_hcd *ehci, 19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct urb *urb, 193455016f10e31bb15b85d8c500f979dfdceb37d548Al Viro gfp_t mem_flags 19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_sitd *sitd; 19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t sitd_dma; 19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_sched *iso_sched; 19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iso_sched = iso_sched_alloc (urb->number_of_packets, mem_flags); 19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (iso_sched == NULL) 19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19476dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese sitd_sched_init(ehci, iso_sched, stream, urb); 19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* allocate/init sITDs */ 19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&ehci->lock, flags); 19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < urb->number_of_packets; i++) { 19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NOTE: for now, we don't try to handle wraparound cases 19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for IN (using sitd->hw_backpointer, like a FSTN), which 19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * means we never need two sitds for full speed packets. 19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* free_list.next might be cache-hot ... but maybe 19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the HC caches it too. avoid that issue for now. 19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* prefer previously-allocated sitds */ 19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!list_empty(&stream->free_list)) { 19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd = list_entry (stream->free_list.prev, 19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_sitd, sitd_list); 19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del (&sitd->sitd_list); 19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd_dma = sitd->sitd_dma; 19683d01f0fe6b66dd34511eaf35e06764b8997187bcKarsten Wiese } else { 19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&ehci->lock, flags); 19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags, 19711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &sitd_dma); 19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&ehci->lock, flags); 19733d01f0fe6b66dd34511eaf35e06764b8997187bcKarsten Wiese if (!sitd) { 19743d01f0fe6b66dd34511eaf35e06764b8997187bcKarsten Wiese iso_sched_free(stream, iso_sched); 19753d01f0fe6b66dd34511eaf35e06764b8997187bcKarsten Wiese spin_unlock_irqrestore(&ehci->lock, flags); 19763d01f0fe6b66dd34511eaf35e06764b8997187bcKarsten Wiese return -ENOMEM; 19773d01f0fe6b66dd34511eaf35e06764b8997187bcKarsten Wiese } 19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset (sitd, 0, sizeof *sitd); 19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd->sitd_dma = sitd_dma; 19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_add (&sitd->sitd_list, &iso_sched->td_list); 19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* temporarily store schedule info in hcpriv */ 19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->hcpriv = iso_sched; 19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->error_count = 0; 19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&ehci->lock, flags); 19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void 19966dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roesesitd_patch( 19976dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese struct ehci_hcd *ehci, 19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream, 19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_sitd *sitd, 20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_sched *iso_sched, 20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned index 20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_packet *uf = &iso_sched->packet [index]; 20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u64 bufp = uf->bufp; 20061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20076dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese sitd->hw_next = EHCI_LIST_END(ehci); 20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd->hw_fullspeed_ep = stream->address; 20091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd->hw_uframe = stream->splits; 20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd->hw_results = uf->transaction; 20116dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese sitd->hw_backpointer = EHCI_LIST_END(ehci); 20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bufp = uf->bufp; 20146dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese sitd->hw_buf[0] = cpu_to_hc32(ehci, bufp); 20156dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese sitd->hw_buf_hi[0] = cpu_to_hc32(ehci, bufp >> 32); 20161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20176dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese sitd->hw_buf[1] = cpu_to_hc32(ehci, uf->buf1); 20181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (uf->cross) 20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bufp += 4096; 20206dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese sitd->hw_buf_hi[1] = cpu_to_hc32(ehci, bufp >> 32); 20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd->index = index; 20221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void 20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd) 20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* note: sitd ordering could matter (CSPLIT then SSPLIT) */ 20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd->sitd_next = ehci->pshadow [frame]; 20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd->hw_next = ehci->periodic [frame]; 20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci->pshadow [frame].sitd = sitd; 20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd->frame = frame; 20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb (); 20336dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese ehci->periodic[frame] = cpu_to_hc32(ehci, sitd->sitd_dma | Q_TYPE_SITD); 20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* fit urb's sitds into the selected schedule slot; activate as needed */ 20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 20381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssitd_link_urb ( 20391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_hcd *ehci, 20401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct urb *urb, 20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned mod, 20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream 20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) 20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int packet; 20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned next_uframe; 20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_sched *sched = urb->hcpriv; 20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_sitd *sitd; 20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_uframe = stream->next_uframe; 20511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (list_empty(&stream->td_list)) { 20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* usbfs ignores TT bandwidth */ 20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_to_hcd(ehci)->self.bandwidth_allocated 20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds += stream->bandwidth; 20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_vdbg (ehci, 20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "sched devp %s ep%d%s-iso [%d] %dms/%04x\n", 20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->dev->devpath, stream->bEndpointAddress & 0x0f, 20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", 2060bccbefaae050186bed3bcc74b1fd1a9b8c6710b2Alan Stern (next_uframe >> 3) & (ehci->periodic_size - 1), 20616dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese stream->interval, hc32_to_cpu(ehci, stream->splits)); 20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 206305570297ecbe834b1756b522412b68eaffb9ab11Alex He 206405570297ecbe834b1756b522412b68eaffb9ab11Alex He if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { 2065ad93562bdeecdded7d02eaaaf1aa5705ab57b1b7Andiry Xu if (ehci->amd_pll_fix == 1) 2066ad93562bdeecdded7d02eaaaf1aa5705ab57b1b7Andiry Xu usb_amd_quirk_pll_disable(); 206705570297ecbe834b1756b522412b68eaffb9ab11Alex He } 206805570297ecbe834b1756b522412b68eaffb9ab11Alex He 20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; 20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* fill sITDs frame by frame */ 20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (packet = 0, sitd = NULL; 20731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds packet < urb->number_of_packets; 20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds packet++) { 20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ASSERT: we have all necessary sitds */ 20771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_ON (list_empty (&sched->td_list)); 20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ASSERT: no itds for this endpoint in this frame */ 20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd = list_entry (sched->td_list.next, 20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_sitd, sitd_list); 20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_move_tail (&sitd->sitd_list, &stream->td_list); 20841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd->stream = iso_stream_get (stream); 2085508db8c954d55ed30f870d2c24d741ba6269d13cKarsten Wiese sitd->urb = urb; 20861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20876dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese sitd_patch(ehci, stream, sitd, sched, packet); 2088bccbefaae050186bed3bcc74b1fd1a9b8c6710b2Alan Stern sitd_link(ehci, (next_uframe >> 3) & (ehci->periodic_size - 1), 20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd); 20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds next_uframe += stream->interval << 3; 20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2093bccbefaae050186bed3bcc74b1fd1a9b8c6710b2Alan Stern stream->next_uframe = next_uframe & (mod - 1); 20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't need that schedule data any more */ 20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iso_sched_free (stream, sched); 20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->hcpriv = NULL; 20981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timer_action (ehci, TIMER_IO_WATCHDOG); 210001c17142659c02d8cd4c67acdd8358180c5c4fb6David Brownell return enable_periodic(ehci); 21011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \ 210653bd6a601a87bb6d0df844872bc15fd4e8d127ceDavid Brownell | SITD_STS_XACT | SITD_STS_MMF) 21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 210830bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell/* Process and recycle a completed SITD. Return true iff its urb completed, 210930bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * and hence its completion callback probably added things to the hardware 211030bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * schedule. 211130bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * 211230bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * Note that we carefully avoid recycling this descriptor until after any 211330bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * completion callback runs, so that it won't be reused quickly. That is, 211430bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * assuming (a) no more than two urbs per frame on this endpoint, and also 211530bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * (b) only this endpoint's completions submit URBs. It seems some silicon 211630bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell * corrupts things if you reuse completed descriptors very quickly... 211730bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell */ 21181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned 21191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssitd_complete ( 21201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_hcd *ehci, 21217d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells struct ehci_sitd *sitd 21221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds) { 21231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct urb *urb = sitd->urb; 21241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_iso_packet_descriptor *desc; 21251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 t; 21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int urb_index = -1; 21271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream = sitd->stream; 21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_device *dev; 212930bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell unsigned retval = false; 21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb_index = sitd->index; 21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds desc = &urb->iso_frame_desc [urb_index]; 21336dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese t = hc32_to_cpup(ehci, &sitd->hw_results); 21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* report transfer status */ 21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (t & SITD_ERRS) { 21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->error_count++; 21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (t & SITD_STS_DBE) 21391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds desc->status = usb_pipein (urb->pipe) 21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ? -ENOSR /* hc couldn't read */ 21411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds : -ECOMM; /* hc couldn't write */ 21421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (t & SITD_STS_BABBLE) 21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds desc->status = -EOVERFLOW; 21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else /* XACT, MMF, etc */ 21451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds desc->status = -EPROTO; 21461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 21471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds desc->status = 0; 2148ec6d67e39f5638c792eb7490bf32586ccb9d8005Alan Stern desc->actual_length = desc->length - SITD_LENGTH(t); 2149ec6d67e39f5638c792eb7490bf32586ccb9d8005Alan Stern urb->actual_length += desc->actual_length; 21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* handle completion now? */ 21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((urb_index + 1) != urb->number_of_packets) 215430bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell goto done; 21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ASSERT: it's really the last sitd for this urb 21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_entry (sitd, &stream->td_list, sitd_list) 21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_ON (sitd->urb == urb); 21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161aa16ca307ee2da304d3a5fc0fc5e50ef8047c9e9David Brownell /* give urb back to the driver; completion often (re)submits */ 21626a8e87b23ff4a979bde5451a242466a4b3f9fe7dAlan Stern dev = urb->dev; 216314c04c0f88f228fee1f412be91d6edcb935c78aaAlan Stern ehci_urb_done(ehci, urb, 0); 216430bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell retval = true; 21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb = NULL; 216601c17142659c02d8cd4c67acdd8358180c5c4fb6David Brownell (void) disable_periodic(ehci); 21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; 21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 216905570297ecbe834b1756b522412b68eaffb9ab11Alex He if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { 2170ad93562bdeecdded7d02eaaaf1aa5705ab57b1b7Andiry Xu if (ehci->amd_pll_fix == 1) 2171ad93562bdeecdded7d02eaaaf1aa5705ab57b1b7Andiry Xu usb_amd_quirk_pll_enable(); 217205570297ecbe834b1756b522412b68eaffb9ab11Alex He } 217305570297ecbe834b1756b522412b68eaffb9ab11Alex He 2174508db8c954d55ed30f870d2c24d741ba6269d13cKarsten Wiese if (list_is_singular(&stream->td_list)) { 21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_to_hcd(ehci)->self.bandwidth_allocated 21761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -= stream->bandwidth; 21771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_vdbg (ehci, 21781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "deschedule devp %s ep%d%s-iso\n", 21791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->devpath, stream->bEndpointAddress & 0x0f, 21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); 21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iso_stream_put (ehci, stream); 21830e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern 218430bf54e62a7926a483b4e36015bb4eb1372e6303David Brownelldone: 218530bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell sitd->urb = NULL; 21860e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern if (ehci->clock_frame != sitd->frame) { 21870e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern /* OK to recycle this SITD now. */ 21880e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern sitd->stream = NULL; 21890e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern list_move(&sitd->sitd_list, &stream->free_list); 21900e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern iso_stream_put(ehci, stream); 21910e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern } else { 21920e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern /* HW might remember this SITD, so we can't recycle it yet. 21930e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern * Move it to a safe place until a new frame starts. 21940e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern */ 21950e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern list_move(&sitd->sitd_list, &ehci->cached_sitd_list); 21960e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern if (stream->refcount == 2) { 21970e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern /* If iso_stream_put() were called here, stream 21980e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern * would be freed. Instead, just prevent reuse. 21990e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern */ 22000e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern stream->ep->hcpriv = NULL; 22010e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern stream->ep = NULL; 22020e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern } 22030e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern } 220430bf54e62a7926a483b4e36015bb4eb1372e6303David Brownell return retval; 22051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22085db539e49fc7471e23bf3c94ca304f008cb7b7f3Olav Kongasstatic int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, 220955016f10e31bb15b85d8c500f979dfdceb37d548Al Viro gfp_t mem_flags) 22101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status = -EINVAL; 22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 22131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ehci_iso_stream *stream; 22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Get iso_stream head */ 22161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream = iso_stream_find (ehci, urb); 22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (stream == NULL) { 22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_dbg (ehci, "can't get iso stream\n"); 22191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 22201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (urb->interval != stream->interval) { 22221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_dbg (ehci, "can't change iso interval %d --> %d\n", 22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stream->interval, urb->interval); 22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef EHCI_URB_TRACE 22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_dbg (ehci, 22291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "submit %p dev%s ep%d%s-iso len %d\n", 22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb, urb->dev->devpath, 22311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_pipeendpoint (urb->pipe), 22321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_pipein (urb->pipe) ? "in" : "out", 22331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds urb->transfer_buffer_length); 22341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 22351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* allocate SITDs */ 22371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = sitd_urb_transaction (stream, ehci, urb, mem_flags); 22381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status < 0) { 22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci_dbg (ehci, "can't init sitds\n"); 22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 22411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* schedule ... need to lock */ 22441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&ehci->lock, flags); 2245541c7d432f76771079e7c295d596ea47cc6a3030Alan Stern if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { 22468de98402652c01839ae321be6cb3054cf5735d83Benjamin Herrenschmidt status = -ESHUTDOWN; 2247e9df41c5c5899259541dc928872cad4d07b82076Alan Stern goto done_not_linked; 2248e9df41c5c5899259541dc928872cad4d07b82076Alan Stern } 2249e9df41c5c5899259541dc928872cad4d07b82076Alan Stern status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); 2250e9df41c5c5899259541dc928872cad4d07b82076Alan Stern if (unlikely(status)) 2251e9df41c5c5899259541dc928872cad4d07b82076Alan Stern goto done_not_linked; 2252e9df41c5c5899259541dc928872cad4d07b82076Alan Stern status = iso_stream_schedule(ehci, urb, stream); 225353bd6a601a87bb6d0df844872bc15fd4e8d127ceDavid Brownell if (status == 0) 22541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); 2255e9df41c5c5899259541dc928872cad4d07b82076Alan Stern else 2256e9df41c5c5899259541dc928872cad4d07b82076Alan Stern usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); 2257e9df41c5c5899259541dc928872cad4d07b82076Alan Sterndone_not_linked: 22581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&ehci->lock, flags); 22591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdone: 22611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status < 0) 22621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iso_stream_put (ehci, stream); 22631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return status; 22641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*-------------------------------------------------------------------------*/ 22671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22680e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Sternstatic void free_cached_lists(struct ehci_hcd *ehci) 22699aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese{ 22709aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese struct ehci_itd *itd, *n; 22710e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern struct ehci_sitd *sitd, *sn; 22729aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese 22739aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) { 22749aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese struct ehci_iso_stream *stream = itd->stream; 22759aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese itd->stream = NULL; 22769aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese list_move(&itd->itd_list, &stream->free_list); 22779aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese iso_stream_put(ehci, stream); 22789aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese } 22790e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern 22800e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern list_for_each_entry_safe(sitd, sn, &ehci->cached_sitd_list, sitd_list) { 22810e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern struct ehci_iso_stream *stream = sitd->stream; 22820e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern sitd->stream = NULL; 22830e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern list_move(&sitd->sitd_list, &stream->free_list); 22840e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern iso_stream_put(ehci, stream); 22850e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern } 22869aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese} 22879aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese 22889aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese/*-------------------------------------------------------------------------*/ 22899aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese 22901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 22917d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsscan_periodic (struct ehci_hcd *ehci) 22921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2293b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern unsigned now_uframe, frame, clock, clock_frame, mod; 22941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned modified; 22951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mod = ehci->periodic_size << 3; 22971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 22991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * When running, scan from last scan point up to "now" 23001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * else clean up by scanning everything that's left. 23011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Touches as few pages as possible: cache-friendly. 23021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 23031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds now_uframe = ehci->next_uframe; 2304e8799906045302776b35b66b16495c575db3b69cAlan Stern if (ehci->rh_state == EHCI_RH_RUNNING) { 230568aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern clock = ehci_read_frame_index(ehci); 2306bccbefaae050186bed3bcc74b1fd1a9b8c6710b2Alan Stern clock_frame = (clock >> 3) & (ehci->periodic_size - 1); 23079aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese } else { 23081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clock = now_uframe + mod - 1; 23099aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese clock_frame = -1; 23109aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese } 23119aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese if (ehci->clock_frame != clock_frame) { 23120e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern free_cached_lists(ehci); 23139aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese ehci->clock_frame = clock_frame; 23149aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese } 2315bccbefaae050186bed3bcc74b1fd1a9b8c6710b2Alan Stern clock &= mod - 1; 2316b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern clock_frame = clock >> 3; 23171e12c910eed82da6971f1c0421a069c680faba2eAlan Stern ++ehci->periodic_stamp; 23181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (;;) { 23201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union ehci_shadow q, *q_p; 23216dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese __hc32 type, *hw_p; 232279592b722e7a8476680197d97352d2cc0f1bffd2David Brownell unsigned incomplete = false; 23231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frame = now_uframe >> 3; 23251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsrestart: 23271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* scan each element in frame's queue for completions */ 23281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q_p = &ehci->pshadow [frame]; 23291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_p = &ehci->periodic [frame]; 23301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q.ptr = q_p->ptr; 23316dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese type = Q_NEXT_TYPE(ehci, *hw_p); 23321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modified = 0; 23331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (q.ptr != NULL) { 23351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned uf; 23361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union ehci_shadow temp; 23371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int live; 23381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2339e8799906045302776b35b66b16495c575db3b69cAlan Stern live = (ehci->rh_state == EHCI_RH_RUNNING); 23406dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese switch (hc32_to_cpu(ehci, type)) { 23411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case Q_TYPE_QH: 23421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* handle any completions */ 23431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp.qh = qh_get (q.qh); 23443807e26d69b9ad3864fe03224ebebc9610d5802eAlek Du type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next); 23451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = q.qh->qh_next; 23461e12c910eed82da6971f1c0421a069c680faba2eAlan Stern if (temp.qh->stamp != ehci->periodic_stamp) { 23471e12c910eed82da6971f1c0421a069c680faba2eAlan Stern modified = qh_completions(ehci, temp.qh); 23481e12c910eed82da6971f1c0421a069c680faba2eAlan Stern if (!modified) 23491e12c910eed82da6971f1c0421a069c680faba2eAlan Stern temp.qh->stamp = ehci->periodic_stamp; 23501e12c910eed82da6971f1c0421a069c680faba2eAlan Stern if (unlikely(list_empty(&temp.qh->qtd_list) || 23511e12c910eed82da6971f1c0421a069c680faba2eAlan Stern temp.qh->needs_rescan)) 23521e12c910eed82da6971f1c0421a069c680faba2eAlan Stern intr_deschedule(ehci, temp.qh); 23531e12c910eed82da6971f1c0421a069c680faba2eAlan Stern } 23541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qh_put (temp.qh); 23551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 23561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case Q_TYPE_FSTN: 23571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* for "save place" FSTNs, look at QH entries 23581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in the previous frame for completions. 23591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 23606dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese if (q.fstn->hw_prev != EHCI_LIST_END(ehci)) { 23611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg ("ignoring completions from FSTNs"); 23621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23636dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese type = Q_NEXT_TYPE(ehci, q.fstn->hw_next); 23641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = q.fstn->fstn_next; 23651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 23661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case Q_TYPE_ITD: 236779592b722e7a8476680197d97352d2cc0f1bffd2David Brownell /* If this ITD is still active, leave it for 236879592b722e7a8476680197d97352d2cc0f1bffd2David Brownell * later processing ... check the next entry. 2369b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern * No need to check for activity unless the 2370b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern * frame is current. 237179592b722e7a8476680197d97352d2cc0f1bffd2David Brownell */ 2372b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern if (frame == clock_frame && live) { 2373b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern rmb(); 2374b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern for (uf = 0; uf < 8; uf++) { 2375b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern if (q.itd->hw_transaction[uf] & 2376b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern ITD_ACTIVE(ehci)) 2377b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern break; 2378b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern } 2379b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern if (uf < 8) { 2380b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern incomplete = true; 2381b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern q_p = &q.itd->itd_next; 2382b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern hw_p = &q.itd->hw_next; 2383b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern type = Q_NEXT_TYPE(ehci, 23846dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese q.itd->hw_next); 2385b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern q = *q_p; 2386b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern break; 2387b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern } 23881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 239079592b722e7a8476680197d97352d2cc0f1bffd2David Brownell /* Take finished ITDs out of the schedule 239179592b722e7a8476680197d97352d2cc0f1bffd2David Brownell * and process them: recycle, maybe report 239279592b722e7a8476680197d97352d2cc0f1bffd2David Brownell * URB completion. HC won't cache the 23931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pointer for much longer, if at all. 23941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 23951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *q_p = q.itd->itd_next; 23963d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu if (!ehci->use_dummy_qh || 23973d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu q.itd->hw_next != EHCI_LIST_END(ehci)) 23983d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu *hw_p = q.itd->hw_next; 23993d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu else 24003d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu *hw_p = ehci->dummy->qh_dma; 24016dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese type = Q_NEXT_TYPE(ehci, q.itd->hw_next); 24021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb(); 24037d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells modified = itd_complete (ehci, q.itd); 24041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = *q_p; 24051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case Q_TYPE_SITD: 240779592b722e7a8476680197d97352d2cc0f1bffd2David Brownell /* If this SITD is still active, leave it for 240879592b722e7a8476680197d97352d2cc0f1bffd2David Brownell * later processing ... check the next entry. 2409b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern * No need to check for activity unless the 2410b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern * frame is current. 241179592b722e7a8476680197d97352d2cc0f1bffd2David Brownell */ 241222e186948a262c9cd377fb43aa50bb3c3f01c468Dmitri Epshtein if (((frame == clock_frame) || 2413bccbefaae050186bed3bcc74b1fd1a9b8c6710b2Alan Stern (((frame + 1) & (ehci->periodic_size - 1)) 241422e186948a262c9cd377fb43aa50bb3c3f01c468Dmitri Epshtein == clock_frame)) 241522e186948a262c9cd377fb43aa50bb3c3f01c468Dmitri Epshtein && live 241622e186948a262c9cd377fb43aa50bb3c3f01c468Dmitri Epshtein && (q.sitd->hw_results & 241722e186948a262c9cd377fb43aa50bb3c3f01c468Dmitri Epshtein SITD_ACTIVE(ehci))) { 241822e186948a262c9cd377fb43aa50bb3c3f01c468Dmitri Epshtein 241979592b722e7a8476680197d97352d2cc0f1bffd2David Brownell incomplete = true; 24201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q_p = &q.sitd->sitd_next; 24211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hw_p = &q.sitd->hw_next; 24226dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese type = Q_NEXT_TYPE(ehci, 24236dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese q.sitd->hw_next); 24241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = *q_p; 24251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 242779592b722e7a8476680197d97352d2cc0f1bffd2David Brownell 242879592b722e7a8476680197d97352d2cc0f1bffd2David Brownell /* Take finished SITDs out of the schedule 242979592b722e7a8476680197d97352d2cc0f1bffd2David Brownell * and process them: recycle, maybe report 243079592b722e7a8476680197d97352d2cc0f1bffd2David Brownell * URB completion. 243179592b722e7a8476680197d97352d2cc0f1bffd2David Brownell */ 24321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *q_p = q.sitd->sitd_next; 24333d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu if (!ehci->use_dummy_qh || 24343d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu q.sitd->hw_next != EHCI_LIST_END(ehci)) 24353d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu *hw_p = q.sitd->hw_next; 24363d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu else 24373d091a6f703906c5680855ff29bd94d051c8c6d8Andiry Xu *hw_p = ehci->dummy->qh_dma; 24386dbd682b7c6d58916096616cdf94852641bc09d9Stefan Roese type = Q_NEXT_TYPE(ehci, q.sitd->hw_next); 24391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb(); 24407d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells modified = sitd_complete (ehci, q.sitd); 24411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = *q_p; 24421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 24441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg ("corrupt type %d frame %d shadow %p", 24451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type, frame, q.ptr); 24461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // BUG (); 24471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q.ptr = NULL; 24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* assume completion callbacks modify the queue */ 2451aa16ca307ee2da304d3a5fc0fc5e50ef8047c9e9David Brownell if (unlikely (modified)) { 2452aa16ca307ee2da304d3a5fc0fc5e50ef8047c9e9David Brownell if (likely(ehci->periodic_sched > 0)) 2453aa16ca307ee2da304d3a5fc0fc5e50ef8047c9e9David Brownell goto restart; 245401c17142659c02d8cd4c67acdd8358180c5c4fb6David Brownell /* short-circuit this scan */ 2455aa16ca307ee2da304d3a5fc0fc5e50ef8047c9e9David Brownell now_uframe = clock; 2456aa16ca307ee2da304d3a5fc0fc5e50ef8047c9e9David Brownell break; 2457aa16ca307ee2da304d3a5fc0fc5e50ef8047c9e9David Brownell } 24581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 24591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 246079592b722e7a8476680197d97352d2cc0f1bffd2David Brownell /* If we can tell we caught up to the hardware, stop now. 246179592b722e7a8476680197d97352d2cc0f1bffd2David Brownell * We can't advance our scan without collecting the ISO 246279592b722e7a8476680197d97352d2cc0f1bffd2David Brownell * transfers that are still pending in this frame. 246379592b722e7a8476680197d97352d2cc0f1bffd2David Brownell */ 2464e8799906045302776b35b66b16495c575db3b69cAlan Stern if (incomplete && ehci->rh_state == EHCI_RH_RUNNING) { 246579592b722e7a8476680197d97352d2cc0f1bffd2David Brownell ehci->next_uframe = now_uframe; 246679592b722e7a8476680197d97352d2cc0f1bffd2David Brownell break; 246779592b722e7a8476680197d97352d2cc0f1bffd2David Brownell } 24681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // FIXME: this assumes we won't get lapped when 24701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // latencies climb; that should be rare, but... 24711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // detect it, and just go all the way around. 24721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // FLR might help detect this case, so long as latencies 24731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // don't exceed periodic_size msec (default 1.024 sec). 24741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // FIXME: likewise assumes HC doesn't halt mid-scan 24761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (now_uframe == clock) { 24781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned now; 24791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2480e8799906045302776b35b66b16495c575db3b69cAlan Stern if (ehci->rh_state != EHCI_RH_RUNNING 2481aa16ca307ee2da304d3a5fc0fc5e50ef8047c9e9David Brownell || ehci->periodic_sched == 0) 24821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ehci->next_uframe = now_uframe; 248468aa95d5d4de31c9348c1628ffa85c805305ebc5Alan Stern now = ehci_read_frame_index(ehci) & (mod - 1); 24851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (now_uframe == now) 24861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 24871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* rescan the rest of this frame, then ... */ 24891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clock = now; 2490b40e43fcc532fa44a375a37d592e32cd0d50fe7aAlan Stern clock_frame = clock >> 3; 24919aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese if (ehci->clock_frame != clock_frame) { 24920e5f231bc16ff9910882fa5b9d64d80e7691cfabAlan Stern free_cached_lists(ehci); 24939aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese ehci->clock_frame = clock_frame; 24941e12c910eed82da6971f1c0421a069c680faba2eAlan Stern ++ehci->periodic_stamp; 24959aa09d2f8f4bc440d6db1c3414d4009642875240Karsten Wiese } 24961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 24971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds now_uframe++; 2498bccbefaae050186bed3bcc74b1fd1a9b8c6710b2Alan Stern now_uframe &= mod - 1; 24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 250053bd6a601a87bb6d0df844872bc15fd4e8d127ceDavid Brownell } 25011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2502