11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Universal Host Controller Interface driver for USB. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Maintainer: Alan Stern <stern@rowland.harvard.edu> 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * (C) Copyright 1999 Linus Torvalds 71da177e4SLinus Torvalds * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com 81da177e4SLinus Torvalds * (C) Copyright 1999 Randy Dunlap 91da177e4SLinus Torvalds * (C) Copyright 1999 Georg Acher, acher@in.tum.de 101da177e4SLinus Torvalds * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de 111da177e4SLinus Torvalds * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch 121da177e4SLinus Torvalds * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at 131da177e4SLinus Torvalds * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface 141da177e4SLinus Torvalds * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). 151da177e4SLinus Torvalds * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) 161da177e4SLinus Torvalds * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu 171da177e4SLinus Torvalds */ 181da177e4SLinus Torvalds 191da177e4SLinus Torvalds static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb); 201da177e4SLinus Torvalds static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb); 211da177e4SLinus Torvalds static void uhci_remove_pending_urbps(struct uhci_hcd *uhci); 221da177e4SLinus Torvalds static void uhci_free_pending_qhs(struct uhci_hcd *uhci); 231da177e4SLinus Torvalds static void uhci_free_pending_tds(struct uhci_hcd *uhci); 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds /* 261da177e4SLinus Torvalds * Technically, updating td->status here is a race, but it's not really a 271da177e4SLinus Torvalds * problem. The worst that can happen is that we set the IOC bit again 281da177e4SLinus Torvalds * generating a spurious interrupt. We could fix this by creating another 291da177e4SLinus Torvalds * QH and leaving the IOC bit always set, but then we would have to play 301da177e4SLinus Torvalds * games with the FSBR code to make sure we get the correct order in all 311da177e4SLinus Torvalds * the cases. I don't think it's worth the effort 321da177e4SLinus Torvalds */ 331da177e4SLinus Torvalds static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) 341da177e4SLinus Torvalds { 35*6c1b445cSAlan Stern if (uhci->is_stopped) 36*6c1b445cSAlan Stern mod_timer(&uhci->stall_timer, jiffies); 371da177e4SLinus Torvalds uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); 381da177e4SLinus Torvalds } 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci) 411da177e4SLinus Torvalds { 421da177e4SLinus Torvalds uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC); 431da177e4SLinus Torvalds } 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds static inline void uhci_moveto_complete(struct uhci_hcd *uhci, 461da177e4SLinus Torvalds struct urb_priv *urbp) 471da177e4SLinus Torvalds { 481da177e4SLinus Torvalds list_move_tail(&urbp->urb_list, &uhci->complete_list); 491da177e4SLinus Torvalds } 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *dev) 521da177e4SLinus Torvalds { 531da177e4SLinus Torvalds dma_addr_t dma_handle; 541da177e4SLinus Torvalds struct uhci_td *td; 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds td = dma_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle); 571da177e4SLinus Torvalds if (!td) 581da177e4SLinus Torvalds return NULL; 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds td->dma_handle = dma_handle; 611da177e4SLinus Torvalds 621da177e4SLinus Torvalds td->link = UHCI_PTR_TERM; 631da177e4SLinus Torvalds td->buffer = 0; 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds td->frame = -1; 661da177e4SLinus Torvalds td->dev = dev; 671da177e4SLinus Torvalds 681da177e4SLinus Torvalds INIT_LIST_HEAD(&td->list); 691da177e4SLinus Torvalds INIT_LIST_HEAD(&td->remove_list); 701da177e4SLinus Torvalds INIT_LIST_HEAD(&td->fl_list); 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds usb_get_dev(dev); 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds return td; 751da177e4SLinus Torvalds } 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds static inline void uhci_fill_td(struct uhci_td *td, u32 status, 781da177e4SLinus Torvalds u32 token, u32 buffer) 791da177e4SLinus Torvalds { 801da177e4SLinus Torvalds td->status = cpu_to_le32(status); 811da177e4SLinus Torvalds td->token = cpu_to_le32(token); 821da177e4SLinus Torvalds td->buffer = cpu_to_le32(buffer); 831da177e4SLinus Torvalds } 841da177e4SLinus Torvalds 851da177e4SLinus Torvalds /* 861da177e4SLinus Torvalds * We insert Isochronous URB's directly into the frame list at the beginning 871da177e4SLinus Torvalds */ 881da177e4SLinus Torvalds static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum) 891da177e4SLinus Torvalds { 901da177e4SLinus Torvalds framenum &= (UHCI_NUMFRAMES - 1); 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds td->frame = framenum; 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds /* Is there a TD already mapped there? */ 951da177e4SLinus Torvalds if (uhci->fl->frame_cpu[framenum]) { 961da177e4SLinus Torvalds struct uhci_td *ftd, *ltd; 971da177e4SLinus Torvalds 981da177e4SLinus Torvalds ftd = uhci->fl->frame_cpu[framenum]; 991da177e4SLinus Torvalds ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list); 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds list_add_tail(&td->fl_list, &ftd->fl_list); 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds td->link = ltd->link; 1041da177e4SLinus Torvalds wmb(); 1051da177e4SLinus Torvalds ltd->link = cpu_to_le32(td->dma_handle); 1061da177e4SLinus Torvalds } else { 1071da177e4SLinus Torvalds td->link = uhci->fl->frame[framenum]; 1081da177e4SLinus Torvalds wmb(); 1091da177e4SLinus Torvalds uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle); 1101da177e4SLinus Torvalds uhci->fl->frame_cpu[framenum] = td; 1111da177e4SLinus Torvalds } 1121da177e4SLinus Torvalds } 1131da177e4SLinus Torvalds 1141da177e4SLinus Torvalds static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td) 1151da177e4SLinus Torvalds { 1161da177e4SLinus Torvalds /* If it's not inserted, don't remove it */ 1171da177e4SLinus Torvalds if (td->frame == -1 && list_empty(&td->fl_list)) 1181da177e4SLinus Torvalds return; 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) { 1211da177e4SLinus Torvalds if (list_empty(&td->fl_list)) { 1221da177e4SLinus Torvalds uhci->fl->frame[td->frame] = td->link; 1231da177e4SLinus Torvalds uhci->fl->frame_cpu[td->frame] = NULL; 1241da177e4SLinus Torvalds } else { 1251da177e4SLinus Torvalds struct uhci_td *ntd; 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list); 1281da177e4SLinus Torvalds uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle); 1291da177e4SLinus Torvalds uhci->fl->frame_cpu[td->frame] = ntd; 1301da177e4SLinus Torvalds } 1311da177e4SLinus Torvalds } else { 1321da177e4SLinus Torvalds struct uhci_td *ptd; 1331da177e4SLinus Torvalds 1341da177e4SLinus Torvalds ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list); 1351da177e4SLinus Torvalds ptd->link = td->link; 1361da177e4SLinus Torvalds } 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds wmb(); 1391da177e4SLinus Torvalds td->link = UHCI_PTR_TERM; 1401da177e4SLinus Torvalds 1411da177e4SLinus Torvalds list_del_init(&td->fl_list); 1421da177e4SLinus Torvalds td->frame = -1; 1431da177e4SLinus Torvalds } 1441da177e4SLinus Torvalds 1451da177e4SLinus Torvalds /* 1461da177e4SLinus Torvalds * Inserts a td list into qh. 1471da177e4SLinus Torvalds */ 1481da177e4SLinus Torvalds static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, __le32 breadth) 1491da177e4SLinus Torvalds { 1501da177e4SLinus Torvalds struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; 1511da177e4SLinus Torvalds struct uhci_td *td; 1521da177e4SLinus Torvalds __le32 *plink; 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds /* Ordering isn't important here yet since the QH hasn't been */ 1551da177e4SLinus Torvalds /* inserted into the schedule yet */ 1561da177e4SLinus Torvalds plink = &qh->element; 1571da177e4SLinus Torvalds list_for_each_entry(td, &urbp->td_list, list) { 1581da177e4SLinus Torvalds *plink = cpu_to_le32(td->dma_handle) | breadth; 1591da177e4SLinus Torvalds plink = &td->link; 1601da177e4SLinus Torvalds } 1611da177e4SLinus Torvalds *plink = UHCI_PTR_TERM; 1621da177e4SLinus Torvalds } 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td) 1651da177e4SLinus Torvalds { 1661da177e4SLinus Torvalds if (!list_empty(&td->list)) 1671da177e4SLinus Torvalds dev_warn(uhci_dev(uhci), "td %p still in list!\n", td); 1681da177e4SLinus Torvalds if (!list_empty(&td->remove_list)) 1691da177e4SLinus Torvalds dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td); 1701da177e4SLinus Torvalds if (!list_empty(&td->fl_list)) 1711da177e4SLinus Torvalds dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds if (td->dev) 1741da177e4SLinus Torvalds usb_put_dev(td->dev); 1751da177e4SLinus Torvalds 1761da177e4SLinus Torvalds dma_pool_free(uhci->td_pool, td, td->dma_handle); 1771da177e4SLinus Torvalds } 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *dev) 1801da177e4SLinus Torvalds { 1811da177e4SLinus Torvalds dma_addr_t dma_handle; 1821da177e4SLinus Torvalds struct uhci_qh *qh; 1831da177e4SLinus Torvalds 1841da177e4SLinus Torvalds qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); 1851da177e4SLinus Torvalds if (!qh) 1861da177e4SLinus Torvalds return NULL; 1871da177e4SLinus Torvalds 1881da177e4SLinus Torvalds qh->dma_handle = dma_handle; 1891da177e4SLinus Torvalds 1901da177e4SLinus Torvalds qh->element = UHCI_PTR_TERM; 1911da177e4SLinus Torvalds qh->link = UHCI_PTR_TERM; 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds qh->dev = dev; 1941da177e4SLinus Torvalds qh->urbp = NULL; 1951da177e4SLinus Torvalds 1961da177e4SLinus Torvalds INIT_LIST_HEAD(&qh->list); 1971da177e4SLinus Torvalds INIT_LIST_HEAD(&qh->remove_list); 1981da177e4SLinus Torvalds 1991da177e4SLinus Torvalds usb_get_dev(dev); 2001da177e4SLinus Torvalds 2011da177e4SLinus Torvalds return qh; 2021da177e4SLinus Torvalds } 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) 2051da177e4SLinus Torvalds { 2061da177e4SLinus Torvalds if (!list_empty(&qh->list)) 2071da177e4SLinus Torvalds dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh); 2081da177e4SLinus Torvalds if (!list_empty(&qh->remove_list)) 2091da177e4SLinus Torvalds dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh); 2101da177e4SLinus Torvalds 2111da177e4SLinus Torvalds if (qh->dev) 2121da177e4SLinus Torvalds usb_put_dev(qh->dev); 2131da177e4SLinus Torvalds 2141da177e4SLinus Torvalds dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); 2151da177e4SLinus Torvalds } 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds /* 2181da177e4SLinus Torvalds * Append this urb's qh after the last qh in skelqh->list 2191da177e4SLinus Torvalds * 2201da177e4SLinus Torvalds * Note that urb_priv.queue_list doesn't have a separate queue head; 2211da177e4SLinus Torvalds * it's a ring with every element "live". 2221da177e4SLinus Torvalds */ 2231da177e4SLinus Torvalds static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct urb *urb) 2241da177e4SLinus Torvalds { 2251da177e4SLinus Torvalds struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; 2261da177e4SLinus Torvalds struct urb_priv *turbp; 2271da177e4SLinus Torvalds struct uhci_qh *lqh; 2281da177e4SLinus Torvalds 2291da177e4SLinus Torvalds /* Grab the last QH */ 2301da177e4SLinus Torvalds lqh = list_entry(skelqh->list.prev, struct uhci_qh, list); 2311da177e4SLinus Torvalds 2321da177e4SLinus Torvalds /* Point to the next skelqh */ 2331da177e4SLinus Torvalds urbp->qh->link = lqh->link; 2341da177e4SLinus Torvalds wmb(); /* Ordering is important */ 2351da177e4SLinus Torvalds 2361da177e4SLinus Torvalds /* 2371da177e4SLinus Torvalds * Patch QHs for previous endpoint's queued URBs? HC goes 2381da177e4SLinus Torvalds * here next, not to the next skelqh it now points to. 2391da177e4SLinus Torvalds * 2401da177e4SLinus Torvalds * lqh --> td ... --> qh ... --> td --> qh ... --> td 2411da177e4SLinus Torvalds * | | | 2421da177e4SLinus Torvalds * v v v 2431da177e4SLinus Torvalds * +<----------------+-----------------+ 2441da177e4SLinus Torvalds * v 2451da177e4SLinus Torvalds * newqh --> td ... --> td 2461da177e4SLinus Torvalds * | 2471da177e4SLinus Torvalds * v 2481da177e4SLinus Torvalds * ... 2491da177e4SLinus Torvalds * 2501da177e4SLinus Torvalds * The HC could see (and use!) any of these as we write them. 2511da177e4SLinus Torvalds */ 2521da177e4SLinus Torvalds lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; 2531da177e4SLinus Torvalds if (lqh->urbp) { 2541da177e4SLinus Torvalds list_for_each_entry(turbp, &lqh->urbp->queue_list, queue_list) 2551da177e4SLinus Torvalds turbp->qh->link = lqh->link; 2561da177e4SLinus Torvalds } 2571da177e4SLinus Torvalds 2581da177e4SLinus Torvalds list_add_tail(&urbp->qh->list, &skelqh->list); 2591da177e4SLinus Torvalds } 2601da177e4SLinus Torvalds 2611da177e4SLinus Torvalds /* 2621da177e4SLinus Torvalds * Start removal of QH from schedule; it finishes next frame. 2631da177e4SLinus Torvalds * TDs should be unlinked before this is called. 2641da177e4SLinus Torvalds */ 2651da177e4SLinus Torvalds static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) 2661da177e4SLinus Torvalds { 2671da177e4SLinus Torvalds struct uhci_qh *pqh; 2681da177e4SLinus Torvalds __le32 newlink; 2691da177e4SLinus Torvalds 2701da177e4SLinus Torvalds if (!qh) 2711da177e4SLinus Torvalds return; 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds /* 2741da177e4SLinus Torvalds * Only go through the hoops if it's actually linked in 2751da177e4SLinus Torvalds */ 2761da177e4SLinus Torvalds if (!list_empty(&qh->list)) { 2771da177e4SLinus Torvalds 2781da177e4SLinus Torvalds /* If our queue is nonempty, make the next URB the head */ 2791da177e4SLinus Torvalds if (!list_empty(&qh->urbp->queue_list)) { 2801da177e4SLinus Torvalds struct urb_priv *nurbp; 2811da177e4SLinus Torvalds 2821da177e4SLinus Torvalds nurbp = list_entry(qh->urbp->queue_list.next, 2831da177e4SLinus Torvalds struct urb_priv, queue_list); 2841da177e4SLinus Torvalds nurbp->queued = 0; 2851da177e4SLinus Torvalds list_add(&nurbp->qh->list, &qh->list); 2861da177e4SLinus Torvalds newlink = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH; 2871da177e4SLinus Torvalds } else 2881da177e4SLinus Torvalds newlink = qh->link; 2891da177e4SLinus Torvalds 2901da177e4SLinus Torvalds /* Fix up the previous QH's queue to link to either 2911da177e4SLinus Torvalds * the new head of this queue or the start of the 2921da177e4SLinus Torvalds * next endpoint's queue. */ 2931da177e4SLinus Torvalds pqh = list_entry(qh->list.prev, struct uhci_qh, list); 2941da177e4SLinus Torvalds pqh->link = newlink; 2951da177e4SLinus Torvalds if (pqh->urbp) { 2961da177e4SLinus Torvalds struct urb_priv *turbp; 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds list_for_each_entry(turbp, &pqh->urbp->queue_list, 2991da177e4SLinus Torvalds queue_list) 3001da177e4SLinus Torvalds turbp->qh->link = newlink; 3011da177e4SLinus Torvalds } 3021da177e4SLinus Torvalds wmb(); 3031da177e4SLinus Torvalds 3041da177e4SLinus Torvalds /* Leave qh->link in case the HC is on the QH now, it will */ 3051da177e4SLinus Torvalds /* continue the rest of the schedule */ 3061da177e4SLinus Torvalds qh->element = UHCI_PTR_TERM; 3071da177e4SLinus Torvalds 3081da177e4SLinus Torvalds list_del_init(&qh->list); 3091da177e4SLinus Torvalds } 3101da177e4SLinus Torvalds 3111da177e4SLinus Torvalds list_del_init(&qh->urbp->queue_list); 3121da177e4SLinus Torvalds qh->urbp = NULL; 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvalds uhci_get_current_frame_number(uhci); 3151da177e4SLinus Torvalds if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) { 3161da177e4SLinus Torvalds uhci_free_pending_qhs(uhci); 3171da177e4SLinus Torvalds uhci->qh_remove_age = uhci->frame_number; 3181da177e4SLinus Torvalds } 3191da177e4SLinus Torvalds 3201da177e4SLinus Torvalds /* Check to see if the remove list is empty. Set the IOC bit */ 3211da177e4SLinus Torvalds /* to force an interrupt so we can remove the QH */ 3221da177e4SLinus Torvalds if (list_empty(&uhci->qh_remove_list)) 3231da177e4SLinus Torvalds uhci_set_next_interrupt(uhci); 3241da177e4SLinus Torvalds 3251da177e4SLinus Torvalds list_add(&qh->remove_list, &uhci->qh_remove_list); 3261da177e4SLinus Torvalds } 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle) 3291da177e4SLinus Torvalds { 3301da177e4SLinus Torvalds struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; 3311da177e4SLinus Torvalds struct uhci_td *td; 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds list_for_each_entry(td, &urbp->td_list, list) { 3341da177e4SLinus Torvalds if (toggle) 3351da177e4SLinus Torvalds td->token |= cpu_to_le32(TD_TOKEN_TOGGLE); 3361da177e4SLinus Torvalds else 3371da177e4SLinus Torvalds td->token &= ~cpu_to_le32(TD_TOKEN_TOGGLE); 3381da177e4SLinus Torvalds 3391da177e4SLinus Torvalds toggle ^= 1; 3401da177e4SLinus Torvalds } 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvalds return toggle; 3431da177e4SLinus Torvalds } 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds /* This function will append one URB's QH to another URB's QH. This is for */ 3461da177e4SLinus Torvalds /* queuing interrupt, control or bulk transfers */ 3471da177e4SLinus Torvalds static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, struct urb *urb) 3481da177e4SLinus Torvalds { 3491da177e4SLinus Torvalds struct urb_priv *eurbp, *urbp, *furbp, *lurbp; 3501da177e4SLinus Torvalds struct uhci_td *lltd; 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds eurbp = eurb->hcpriv; 3531da177e4SLinus Torvalds urbp = urb->hcpriv; 3541da177e4SLinus Torvalds 3551da177e4SLinus Torvalds /* Find the first URB in the queue */ 3561da177e4SLinus Torvalds furbp = eurbp; 3571da177e4SLinus Torvalds if (eurbp->queued) { 3581da177e4SLinus Torvalds list_for_each_entry(furbp, &eurbp->queue_list, queue_list) 3591da177e4SLinus Torvalds if (!furbp->queued) 3601da177e4SLinus Torvalds break; 3611da177e4SLinus Torvalds } 3621da177e4SLinus Torvalds 3631da177e4SLinus Torvalds lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list); 3641da177e4SLinus Torvalds 3651da177e4SLinus Torvalds lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list); 3661da177e4SLinus Torvalds 3671da177e4SLinus Torvalds /* Control transfers always start with toggle 0 */ 3681da177e4SLinus Torvalds if (!usb_pipecontrol(urb->pipe)) 3691da177e4SLinus Torvalds usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), 3701da177e4SLinus Torvalds usb_pipeout(urb->pipe), 3711da177e4SLinus Torvalds uhci_fixup_toggle(urb, 3721da177e4SLinus Torvalds uhci_toggle(td_token(lltd)) ^ 1)); 3731da177e4SLinus Torvalds 3741da177e4SLinus Torvalds /* All qh's in the queue need to link to the next queue */ 3751da177e4SLinus Torvalds urbp->qh->link = eurbp->qh->link; 3761da177e4SLinus Torvalds 3771da177e4SLinus Torvalds wmb(); /* Make sure we flush everything */ 3781da177e4SLinus Torvalds 3791da177e4SLinus Torvalds lltd->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH; 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds list_add_tail(&urbp->queue_list, &furbp->queue_list); 3821da177e4SLinus Torvalds 3831da177e4SLinus Torvalds urbp->queued = 1; 3841da177e4SLinus Torvalds } 3851da177e4SLinus Torvalds 3861da177e4SLinus Torvalds static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb) 3871da177e4SLinus Torvalds { 3881da177e4SLinus Torvalds struct urb_priv *urbp, *nurbp, *purbp, *turbp; 3891da177e4SLinus Torvalds struct uhci_td *pltd; 3901da177e4SLinus Torvalds unsigned int toggle; 3911da177e4SLinus Torvalds 3921da177e4SLinus Torvalds urbp = urb->hcpriv; 3931da177e4SLinus Torvalds 3941da177e4SLinus Torvalds if (list_empty(&urbp->queue_list)) 3951da177e4SLinus Torvalds return; 3961da177e4SLinus Torvalds 3971da177e4SLinus Torvalds nurbp = list_entry(urbp->queue_list.next, struct urb_priv, queue_list); 3981da177e4SLinus Torvalds 3991da177e4SLinus Torvalds /* 4001da177e4SLinus Torvalds * Fix up the toggle for the following URBs in the queue. 4011da177e4SLinus Torvalds * Only needed for bulk and interrupt: control and isochronous 4021da177e4SLinus Torvalds * endpoints don't propagate toggles between messages. 4031da177e4SLinus Torvalds */ 4041da177e4SLinus Torvalds if (usb_pipebulk(urb->pipe) || usb_pipeint(urb->pipe)) { 4051da177e4SLinus Torvalds if (!urbp->queued) 4061da177e4SLinus Torvalds /* We just set the toggle in uhci_unlink_generic */ 4071da177e4SLinus Torvalds toggle = usb_gettoggle(urb->dev, 4081da177e4SLinus Torvalds usb_pipeendpoint(urb->pipe), 4091da177e4SLinus Torvalds usb_pipeout(urb->pipe)); 4101da177e4SLinus Torvalds else { 4111da177e4SLinus Torvalds /* If we're in the middle of the queue, grab the */ 4121da177e4SLinus Torvalds /* toggle from the TD previous to us */ 4131da177e4SLinus Torvalds purbp = list_entry(urbp->queue_list.prev, 4141da177e4SLinus Torvalds struct urb_priv, queue_list); 4151da177e4SLinus Torvalds pltd = list_entry(purbp->td_list.prev, 4161da177e4SLinus Torvalds struct uhci_td, list); 4171da177e4SLinus Torvalds toggle = uhci_toggle(td_token(pltd)) ^ 1; 4181da177e4SLinus Torvalds } 4191da177e4SLinus Torvalds 4201da177e4SLinus Torvalds list_for_each_entry(turbp, &urbp->queue_list, queue_list) { 4211da177e4SLinus Torvalds if (!turbp->queued) 4221da177e4SLinus Torvalds break; 4231da177e4SLinus Torvalds toggle = uhci_fixup_toggle(turbp->urb, toggle); 4241da177e4SLinus Torvalds } 4251da177e4SLinus Torvalds 4261da177e4SLinus Torvalds usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), 4271da177e4SLinus Torvalds usb_pipeout(urb->pipe), toggle); 4281da177e4SLinus Torvalds } 4291da177e4SLinus Torvalds 4301da177e4SLinus Torvalds if (urbp->queued) { 4311da177e4SLinus Torvalds /* We're somewhere in the middle (or end). The case where 4321da177e4SLinus Torvalds * we're at the head is handled in uhci_remove_qh(). */ 4331da177e4SLinus Torvalds purbp = list_entry(urbp->queue_list.prev, struct urb_priv, 4341da177e4SLinus Torvalds queue_list); 4351da177e4SLinus Torvalds 4361da177e4SLinus Torvalds pltd = list_entry(purbp->td_list.prev, struct uhci_td, list); 4371da177e4SLinus Torvalds if (nurbp->queued) 4381da177e4SLinus Torvalds pltd->link = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH; 4391da177e4SLinus Torvalds else 4401da177e4SLinus Torvalds /* The next URB happens to be the beginning, so */ 4411da177e4SLinus Torvalds /* we're the last, end the chain */ 4421da177e4SLinus Torvalds pltd->link = UHCI_PTR_TERM; 4431da177e4SLinus Torvalds } 4441da177e4SLinus Torvalds 4451da177e4SLinus Torvalds /* urbp->queue_list is handled in uhci_remove_qh() */ 4461da177e4SLinus Torvalds } 4471da177e4SLinus Torvalds 4481da177e4SLinus Torvalds static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *urb) 4491da177e4SLinus Torvalds { 4501da177e4SLinus Torvalds struct urb_priv *urbp; 4511da177e4SLinus Torvalds 4521da177e4SLinus Torvalds urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC); 4531da177e4SLinus Torvalds if (!urbp) 4541da177e4SLinus Torvalds return NULL; 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds memset((void *)urbp, 0, sizeof(*urbp)); 4571da177e4SLinus Torvalds 4581da177e4SLinus Torvalds urbp->inserttime = jiffies; 4591da177e4SLinus Torvalds urbp->fsbrtime = jiffies; 4601da177e4SLinus Torvalds urbp->urb = urb; 4611da177e4SLinus Torvalds 4621da177e4SLinus Torvalds INIT_LIST_HEAD(&urbp->td_list); 4631da177e4SLinus Torvalds INIT_LIST_HEAD(&urbp->queue_list); 4641da177e4SLinus Torvalds INIT_LIST_HEAD(&urbp->urb_list); 4651da177e4SLinus Torvalds 4661da177e4SLinus Torvalds list_add_tail(&urbp->urb_list, &uhci->urb_list); 4671da177e4SLinus Torvalds 4681da177e4SLinus Torvalds urb->hcpriv = urbp; 4691da177e4SLinus Torvalds 4701da177e4SLinus Torvalds return urbp; 4711da177e4SLinus Torvalds } 4721da177e4SLinus Torvalds 4731da177e4SLinus Torvalds static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td) 4741da177e4SLinus Torvalds { 4751da177e4SLinus Torvalds struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; 4761da177e4SLinus Torvalds 4771da177e4SLinus Torvalds td->urb = urb; 4781da177e4SLinus Torvalds 4791da177e4SLinus Torvalds list_add_tail(&td->list, &urbp->td_list); 4801da177e4SLinus Torvalds } 4811da177e4SLinus Torvalds 4821da177e4SLinus Torvalds static void uhci_remove_td_from_urb(struct uhci_td *td) 4831da177e4SLinus Torvalds { 4841da177e4SLinus Torvalds if (list_empty(&td->list)) 4851da177e4SLinus Torvalds return; 4861da177e4SLinus Torvalds 4871da177e4SLinus Torvalds list_del_init(&td->list); 4881da177e4SLinus Torvalds 4891da177e4SLinus Torvalds td->urb = NULL; 4901da177e4SLinus Torvalds } 4911da177e4SLinus Torvalds 4921da177e4SLinus Torvalds static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb) 4931da177e4SLinus Torvalds { 4941da177e4SLinus Torvalds struct uhci_td *td, *tmp; 4951da177e4SLinus Torvalds struct urb_priv *urbp; 4961da177e4SLinus Torvalds 4971da177e4SLinus Torvalds urbp = (struct urb_priv *)urb->hcpriv; 4981da177e4SLinus Torvalds if (!urbp) 4991da177e4SLinus Torvalds return; 5001da177e4SLinus Torvalds 5011da177e4SLinus Torvalds if (!list_empty(&urbp->urb_list)) 5021da177e4SLinus Torvalds dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list " 5031da177e4SLinus Torvalds "or uhci->remove_list!\n", urb); 5041da177e4SLinus Torvalds 5051da177e4SLinus Torvalds uhci_get_current_frame_number(uhci); 5061da177e4SLinus Torvalds if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) { 5071da177e4SLinus Torvalds uhci_free_pending_tds(uhci); 5081da177e4SLinus Torvalds uhci->td_remove_age = uhci->frame_number; 5091da177e4SLinus Torvalds } 5101da177e4SLinus Torvalds 5111da177e4SLinus Torvalds /* Check to see if the remove list is empty. Set the IOC bit */ 5121da177e4SLinus Torvalds /* to force an interrupt so we can remove the TD's*/ 5131da177e4SLinus Torvalds if (list_empty(&uhci->td_remove_list)) 5141da177e4SLinus Torvalds uhci_set_next_interrupt(uhci); 5151da177e4SLinus Torvalds 5161da177e4SLinus Torvalds list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { 5171da177e4SLinus Torvalds uhci_remove_td_from_urb(td); 5181da177e4SLinus Torvalds uhci_remove_td(uhci, td); 5191da177e4SLinus Torvalds list_add(&td->remove_list, &uhci->td_remove_list); 5201da177e4SLinus Torvalds } 5211da177e4SLinus Torvalds 5221da177e4SLinus Torvalds urb->hcpriv = NULL; 5231da177e4SLinus Torvalds kmem_cache_free(uhci_up_cachep, urbp); 5241da177e4SLinus Torvalds } 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds static void uhci_inc_fsbr(struct uhci_hcd *uhci, struct urb *urb) 5271da177e4SLinus Torvalds { 5281da177e4SLinus Torvalds struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvalds if ((!(urb->transfer_flags & URB_NO_FSBR)) && !urbp->fsbr) { 5311da177e4SLinus Torvalds urbp->fsbr = 1; 5321da177e4SLinus Torvalds if (!uhci->fsbr++ && !uhci->fsbrtimeout) 5331da177e4SLinus Torvalds uhci->skel_term_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH; 5341da177e4SLinus Torvalds } 5351da177e4SLinus Torvalds } 5361da177e4SLinus Torvalds 5371da177e4SLinus Torvalds static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb) 5381da177e4SLinus Torvalds { 5391da177e4SLinus Torvalds struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; 5401da177e4SLinus Torvalds 5411da177e4SLinus Torvalds if ((!(urb->transfer_flags & URB_NO_FSBR)) && urbp->fsbr) { 5421da177e4SLinus Torvalds urbp->fsbr = 0; 5431da177e4SLinus Torvalds if (!--uhci->fsbr) 5441da177e4SLinus Torvalds uhci->fsbrtimeout = jiffies + FSBR_DELAY; 5451da177e4SLinus Torvalds } 5461da177e4SLinus Torvalds } 5471da177e4SLinus Torvalds 5481da177e4SLinus Torvalds /* 5491da177e4SLinus Torvalds * Map status to standard result codes 5501da177e4SLinus Torvalds * 5511da177e4SLinus Torvalds * <status> is (td_status(td) & 0xF60000), a.k.a. 5521da177e4SLinus Torvalds * uhci_status_bits(td_status(td)). 5531da177e4SLinus Torvalds * Note: <status> does not include the TD_CTRL_NAK bit. 5541da177e4SLinus Torvalds * <dir_out> is True for output TDs and False for input TDs. 5551da177e4SLinus Torvalds */ 5561da177e4SLinus Torvalds static int uhci_map_status(int status, int dir_out) 5571da177e4SLinus Torvalds { 5581da177e4SLinus Torvalds if (!status) 5591da177e4SLinus Torvalds return 0; 5601da177e4SLinus Torvalds if (status & TD_CTRL_BITSTUFF) /* Bitstuff error */ 5611da177e4SLinus Torvalds return -EPROTO; 5621da177e4SLinus Torvalds if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */ 5631da177e4SLinus Torvalds if (dir_out) 5641da177e4SLinus Torvalds return -EPROTO; 5651da177e4SLinus Torvalds else 5661da177e4SLinus Torvalds return -EILSEQ; 5671da177e4SLinus Torvalds } 5681da177e4SLinus Torvalds if (status & TD_CTRL_BABBLE) /* Babble */ 5691da177e4SLinus Torvalds return -EOVERFLOW; 5701da177e4SLinus Torvalds if (status & TD_CTRL_DBUFERR) /* Buffer error */ 5711da177e4SLinus Torvalds return -ENOSR; 5721da177e4SLinus Torvalds if (status & TD_CTRL_STALLED) /* Stalled */ 5731da177e4SLinus Torvalds return -EPIPE; 5741da177e4SLinus Torvalds WARN_ON(status & TD_CTRL_ACTIVE); /* Active */ 5751da177e4SLinus Torvalds return 0; 5761da177e4SLinus Torvalds } 5771da177e4SLinus Torvalds 5781da177e4SLinus Torvalds /* 5791da177e4SLinus Torvalds * Control transfers 5801da177e4SLinus Torvalds */ 5811da177e4SLinus Torvalds static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb) 5821da177e4SLinus Torvalds { 5831da177e4SLinus Torvalds struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; 5841da177e4SLinus Torvalds struct uhci_td *td; 5851da177e4SLinus Torvalds struct uhci_qh *qh, *skelqh; 5861da177e4SLinus Torvalds unsigned long destination, status; 5871da177e4SLinus Torvalds int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); 5881da177e4SLinus Torvalds int len = urb->transfer_buffer_length; 5891da177e4SLinus Torvalds dma_addr_t data = urb->transfer_dma; 5901da177e4SLinus Torvalds 5911da177e4SLinus Torvalds /* The "pipe" thing contains the destination in bits 8--18 */ 5921da177e4SLinus Torvalds destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; 5931da177e4SLinus Torvalds 5941da177e4SLinus Torvalds /* 3 errors */ 5951da177e4SLinus Torvalds status = TD_CTRL_ACTIVE | uhci_maxerr(3); 5961da177e4SLinus Torvalds if (urb->dev->speed == USB_SPEED_LOW) 5971da177e4SLinus Torvalds status |= TD_CTRL_LS; 5981da177e4SLinus Torvalds 5991da177e4SLinus Torvalds /* 6001da177e4SLinus Torvalds * Build the TD for the control request setup packet 6011da177e4SLinus Torvalds */ 6021da177e4SLinus Torvalds td = uhci_alloc_td(uhci, urb->dev); 6031da177e4SLinus Torvalds if (!td) 6041da177e4SLinus Torvalds return -ENOMEM; 6051da177e4SLinus Torvalds 6061da177e4SLinus Torvalds uhci_add_td_to_urb(urb, td); 6071da177e4SLinus Torvalds uhci_fill_td(td, status, destination | uhci_explen(7), 6081da177e4SLinus Torvalds urb->setup_dma); 6091da177e4SLinus Torvalds 6101da177e4SLinus Torvalds /* 6111da177e4SLinus Torvalds * If direction is "send", change the packet ID from SETUP (0x2D) 6121da177e4SLinus Torvalds * to OUT (0xE1). Else change it from SETUP to IN (0x69) and 6131da177e4SLinus Torvalds * set Short Packet Detect (SPD) for all data packets. 6141da177e4SLinus Torvalds */ 6151da177e4SLinus Torvalds if (usb_pipeout(urb->pipe)) 6161da177e4SLinus Torvalds destination ^= (USB_PID_SETUP ^ USB_PID_OUT); 6171da177e4SLinus Torvalds else { 6181da177e4SLinus Torvalds destination ^= (USB_PID_SETUP ^ USB_PID_IN); 6191da177e4SLinus Torvalds status |= TD_CTRL_SPD; 6201da177e4SLinus Torvalds } 6211da177e4SLinus Torvalds 6221da177e4SLinus Torvalds /* 6231da177e4SLinus Torvalds * Build the DATA TD's 6241da177e4SLinus Torvalds */ 6251da177e4SLinus Torvalds while (len > 0) { 6261da177e4SLinus Torvalds int pktsze = len; 6271da177e4SLinus Torvalds 6281da177e4SLinus Torvalds if (pktsze > maxsze) 6291da177e4SLinus Torvalds pktsze = maxsze; 6301da177e4SLinus Torvalds 6311da177e4SLinus Torvalds td = uhci_alloc_td(uhci, urb->dev); 6321da177e4SLinus Torvalds if (!td) 6331da177e4SLinus Torvalds return -ENOMEM; 6341da177e4SLinus Torvalds 6351da177e4SLinus Torvalds /* Alternate Data0/1 (start with Data1) */ 6361da177e4SLinus Torvalds destination ^= TD_TOKEN_TOGGLE; 6371da177e4SLinus Torvalds 6381da177e4SLinus Torvalds uhci_add_td_to_urb(urb, td); 6391da177e4SLinus Torvalds uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1), 6401da177e4SLinus Torvalds data); 6411da177e4SLinus Torvalds 6421da177e4SLinus Torvalds data += pktsze; 6431da177e4SLinus Torvalds len -= pktsze; 6441da177e4SLinus Torvalds } 6451da177e4SLinus Torvalds 6461da177e4SLinus Torvalds /* 6471da177e4SLinus Torvalds * Build the final TD for control status 6481da177e4SLinus Torvalds */ 6491da177e4SLinus Torvalds td = uhci_alloc_td(uhci, urb->dev); 6501da177e4SLinus Torvalds if (!td) 6511da177e4SLinus Torvalds return -ENOMEM; 6521da177e4SLinus Torvalds 6531da177e4SLinus Torvalds /* 6541da177e4SLinus Torvalds * It's IN if the pipe is an output pipe or we're not expecting 6551da177e4SLinus Torvalds * data back. 6561da177e4SLinus Torvalds */ 6571da177e4SLinus Torvalds destination &= ~TD_TOKEN_PID_MASK; 6581da177e4SLinus Torvalds if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length) 6591da177e4SLinus Torvalds destination |= USB_PID_IN; 6601da177e4SLinus Torvalds else 6611da177e4SLinus Torvalds destination |= USB_PID_OUT; 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds destination |= TD_TOKEN_TOGGLE; /* End in Data1 */ 6641da177e4SLinus Torvalds 6651da177e4SLinus Torvalds status &= ~TD_CTRL_SPD; 6661da177e4SLinus Torvalds 6671da177e4SLinus Torvalds uhci_add_td_to_urb(urb, td); 6681da177e4SLinus Torvalds uhci_fill_td(td, status | TD_CTRL_IOC, 6691da177e4SLinus Torvalds destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0); 6701da177e4SLinus Torvalds 6711da177e4SLinus Torvalds qh = uhci_alloc_qh(uhci, urb->dev); 6721da177e4SLinus Torvalds if (!qh) 6731da177e4SLinus Torvalds return -ENOMEM; 6741da177e4SLinus Torvalds 6751da177e4SLinus Torvalds urbp->qh = qh; 6761da177e4SLinus Torvalds qh->urbp = urbp; 6771da177e4SLinus Torvalds 6781da177e4SLinus Torvalds uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH); 6791da177e4SLinus Torvalds 6801da177e4SLinus Torvalds /* Low-speed transfers get a different queue, and won't hog the bus. 6811da177e4SLinus Torvalds * Also, some devices enumerate better without FSBR; the easiest way 6821da177e4SLinus Torvalds * to do that is to put URBs on the low-speed queue while the device 6831da177e4SLinus Torvalds * is in the DEFAULT state. */ 6841da177e4SLinus Torvalds if (urb->dev->speed == USB_SPEED_LOW || 6851da177e4SLinus Torvalds urb->dev->state == USB_STATE_DEFAULT) 6861da177e4SLinus Torvalds skelqh = uhci->skel_ls_control_qh; 6871da177e4SLinus Torvalds else { 6881da177e4SLinus Torvalds skelqh = uhci->skel_fs_control_qh; 6891da177e4SLinus Torvalds uhci_inc_fsbr(uhci, urb); 6901da177e4SLinus Torvalds } 6911da177e4SLinus Torvalds 6921da177e4SLinus Torvalds if (eurb) 6931da177e4SLinus Torvalds uhci_append_queued_urb(uhci, eurb, urb); 6941da177e4SLinus Torvalds else 6951da177e4SLinus Torvalds uhci_insert_qh(uhci, skelqh, urb); 6961da177e4SLinus Torvalds 6971da177e4SLinus Torvalds return -EINPROGRESS; 6981da177e4SLinus Torvalds } 6991da177e4SLinus Torvalds 7001da177e4SLinus Torvalds /* 7011da177e4SLinus Torvalds * If control-IN transfer was short, the status packet wasn't sent. 7021da177e4SLinus Torvalds * This routine changes the element pointer in the QH to point at the 7031da177e4SLinus Torvalds * status TD. It's safe to do this even while the QH is live, because 7041da177e4SLinus Torvalds * the hardware only updates the element pointer following a successful 7051da177e4SLinus Torvalds * transfer. The inactive TD for the short packet won't cause an update, 7061da177e4SLinus Torvalds * so the pointer won't get overwritten. The next time the controller 7071da177e4SLinus Torvalds * sees this QH, it will send the status packet. 7081da177e4SLinus Torvalds */ 7091da177e4SLinus Torvalds static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb) 7101da177e4SLinus Torvalds { 7111da177e4SLinus Torvalds struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; 7121da177e4SLinus Torvalds struct uhci_td *td; 7131da177e4SLinus Torvalds 7141da177e4SLinus Torvalds urbp->short_control_packet = 1; 7151da177e4SLinus Torvalds 7161da177e4SLinus Torvalds td = list_entry(urbp->td_list.prev, struct uhci_td, list); 7171da177e4SLinus Torvalds urbp->qh->element = cpu_to_le32(td->dma_handle); 7181da177e4SLinus Torvalds 7191da177e4SLinus Torvalds return -EINPROGRESS; 7201da177e4SLinus Torvalds } 7211da177e4SLinus Torvalds 7221da177e4SLinus Torvalds 7231da177e4SLinus Torvalds static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) 7241da177e4SLinus Torvalds { 7251da177e4SLinus Torvalds struct list_head *tmp, *head; 7261da177e4SLinus Torvalds struct urb_priv *urbp = urb->hcpriv; 7271da177e4SLinus Torvalds struct uhci_td *td; 7281da177e4SLinus Torvalds unsigned int status; 7291da177e4SLinus Torvalds int ret = 0; 7301da177e4SLinus Torvalds 7311da177e4SLinus Torvalds if (list_empty(&urbp->td_list)) 7321da177e4SLinus Torvalds return -EINVAL; 7331da177e4SLinus Torvalds 7341da177e4SLinus Torvalds head = &urbp->td_list; 7351da177e4SLinus Torvalds 7361da177e4SLinus Torvalds if (urbp->short_control_packet) { 7371da177e4SLinus Torvalds tmp = head->prev; 7381da177e4SLinus Torvalds goto status_stage; 7391da177e4SLinus Torvalds } 7401da177e4SLinus Torvalds 7411da177e4SLinus Torvalds tmp = head->next; 7421da177e4SLinus Torvalds td = list_entry(tmp, struct uhci_td, list); 7431da177e4SLinus Torvalds 7441da177e4SLinus Torvalds /* The first TD is the SETUP stage, check the status, but skip */ 7451da177e4SLinus Torvalds /* the count */ 7461da177e4SLinus Torvalds status = uhci_status_bits(td_status(td)); 7471da177e4SLinus Torvalds if (status & TD_CTRL_ACTIVE) 7481da177e4SLinus Torvalds return -EINPROGRESS; 7491da177e4SLinus Torvalds 7501da177e4SLinus Torvalds if (status) 7511da177e4SLinus Torvalds goto td_error; 7521da177e4SLinus Torvalds 7531da177e4SLinus Torvalds urb->actual_length = 0; 7541da177e4SLinus Torvalds 7551da177e4SLinus Torvalds /* The rest of the TD's (but the last) are data */ 7561da177e4SLinus Torvalds tmp = tmp->next; 7571da177e4SLinus Torvalds while (tmp != head && tmp->next != head) { 7581da177e4SLinus Torvalds unsigned int ctrlstat; 7591da177e4SLinus Torvalds 7601da177e4SLinus Torvalds td = list_entry(tmp, struct uhci_td, list); 7611da177e4SLinus Torvalds tmp = tmp->next; 7621da177e4SLinus Torvalds 7631da177e4SLinus Torvalds ctrlstat = td_status(td); 7641da177e4SLinus Torvalds status = uhci_status_bits(ctrlstat); 7651da177e4SLinus Torvalds if (status & TD_CTRL_ACTIVE) 7661da177e4SLinus Torvalds return -EINPROGRESS; 7671da177e4SLinus Torvalds 7681da177e4SLinus Torvalds urb->actual_length += uhci_actual_length(ctrlstat); 7691da177e4SLinus Torvalds 7701da177e4SLinus Torvalds if (status) 7711da177e4SLinus Torvalds goto td_error; 7721da177e4SLinus Torvalds 7731da177e4SLinus Torvalds /* Check to see if we received a short packet */ 7741da177e4SLinus Torvalds if (uhci_actual_length(ctrlstat) < 7751da177e4SLinus Torvalds uhci_expected_length(td_token(td))) { 7761da177e4SLinus Torvalds if (urb->transfer_flags & URB_SHORT_NOT_OK) { 7771da177e4SLinus Torvalds ret = -EREMOTEIO; 7781da177e4SLinus Torvalds goto err; 7791da177e4SLinus Torvalds } 7801da177e4SLinus Torvalds 7811da177e4SLinus Torvalds if (uhci_packetid(td_token(td)) == USB_PID_IN) 7821da177e4SLinus Torvalds return usb_control_retrigger_status(uhci, urb); 7831da177e4SLinus Torvalds else 7841da177e4SLinus Torvalds return 0; 7851da177e4SLinus Torvalds } 7861da177e4SLinus Torvalds } 7871da177e4SLinus Torvalds 7881da177e4SLinus Torvalds status_stage: 7891da177e4SLinus Torvalds td = list_entry(tmp, struct uhci_td, list); 7901da177e4SLinus Torvalds 7911da177e4SLinus Torvalds /* Control status stage */ 7921da177e4SLinus Torvalds status = td_status(td); 7931da177e4SLinus Torvalds 7941da177e4SLinus Torvalds #ifdef I_HAVE_BUGGY_APC_BACKUPS 7951da177e4SLinus Torvalds /* APC BackUPS Pro kludge */ 7961da177e4SLinus Torvalds /* It tries to send all of the descriptor instead of the amount */ 7971da177e4SLinus Torvalds /* we requested */ 7981da177e4SLinus Torvalds if (status & TD_CTRL_IOC && /* IOC is masked out by uhci_status_bits */ 7991da177e4SLinus Torvalds status & TD_CTRL_ACTIVE && 8001da177e4SLinus Torvalds status & TD_CTRL_NAK) 8011da177e4SLinus Torvalds return 0; 8021da177e4SLinus Torvalds #endif 8031da177e4SLinus Torvalds 8041da177e4SLinus Torvalds status = uhci_status_bits(status); 8051da177e4SLinus Torvalds if (status & TD_CTRL_ACTIVE) 8061da177e4SLinus Torvalds return -EINPROGRESS; 8071da177e4SLinus Torvalds 8081da177e4SLinus Torvalds if (status) 8091da177e4SLinus Torvalds goto td_error; 8101da177e4SLinus Torvalds 8111da177e4SLinus Torvalds return 0; 8121da177e4SLinus Torvalds 8131da177e4SLinus Torvalds td_error: 8141da177e4SLinus Torvalds ret = uhci_map_status(status, uhci_packetout(td_token(td))); 8151da177e4SLinus Torvalds 8161da177e4SLinus Torvalds err: 8171da177e4SLinus Torvalds if ((debug == 1 && ret != -EPIPE) || debug > 1) { 8181da177e4SLinus Torvalds /* Some debugging code */ 8191da177e4SLinus Torvalds dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", 8201da177e4SLinus Torvalds __FUNCTION__, status); 8211da177e4SLinus Torvalds 8221da177e4SLinus Torvalds if (errbuf) { 8231da177e4SLinus Torvalds /* Print the chain for debugging purposes */ 8241da177e4SLinus Torvalds uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); 8251da177e4SLinus Torvalds 8261da177e4SLinus Torvalds lprintk(errbuf); 8271da177e4SLinus Torvalds } 8281da177e4SLinus Torvalds } 8291da177e4SLinus Torvalds 8301da177e4SLinus Torvalds return ret; 8311da177e4SLinus Torvalds } 8321da177e4SLinus Torvalds 8331da177e4SLinus Torvalds /* 8341da177e4SLinus Torvalds * Common submit for bulk and interrupt 8351da177e4SLinus Torvalds */ 8361da177e4SLinus Torvalds static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb, struct uhci_qh *skelqh) 8371da177e4SLinus Torvalds { 8381da177e4SLinus Torvalds struct uhci_td *td; 8391da177e4SLinus Torvalds struct uhci_qh *qh; 8401da177e4SLinus Torvalds unsigned long destination, status; 8411da177e4SLinus Torvalds int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); 8421da177e4SLinus Torvalds int len = urb->transfer_buffer_length; 8431da177e4SLinus Torvalds struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; 8441da177e4SLinus Torvalds dma_addr_t data = urb->transfer_dma; 8451da177e4SLinus Torvalds 8461da177e4SLinus Torvalds if (len < 0) 8471da177e4SLinus Torvalds return -EINVAL; 8481da177e4SLinus Torvalds 8491da177e4SLinus Torvalds /* The "pipe" thing contains the destination in bits 8--18 */ 8501da177e4SLinus Torvalds destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); 8511da177e4SLinus Torvalds 8521da177e4SLinus Torvalds status = uhci_maxerr(3) | TD_CTRL_ACTIVE; 8531da177e4SLinus Torvalds if (urb->dev->speed == USB_SPEED_LOW) 8541da177e4SLinus Torvalds status |= TD_CTRL_LS; 8551da177e4SLinus Torvalds if (usb_pipein(urb->pipe)) 8561da177e4SLinus Torvalds status |= TD_CTRL_SPD; 8571da177e4SLinus Torvalds 8581da177e4SLinus Torvalds /* 8591da177e4SLinus Torvalds * Build the DATA TD's 8601da177e4SLinus Torvalds */ 8611da177e4SLinus Torvalds do { /* Allow zero length packets */ 8621da177e4SLinus Torvalds int pktsze = maxsze; 8631da177e4SLinus Torvalds 8641da177e4SLinus Torvalds if (pktsze >= len) { 8651da177e4SLinus Torvalds pktsze = len; 8661da177e4SLinus Torvalds if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) 8671da177e4SLinus Torvalds status &= ~TD_CTRL_SPD; 8681da177e4SLinus Torvalds } 8691da177e4SLinus Torvalds 8701da177e4SLinus Torvalds td = uhci_alloc_td(uhci, urb->dev); 8711da177e4SLinus Torvalds if (!td) 8721da177e4SLinus Torvalds return -ENOMEM; 8731da177e4SLinus Torvalds 8741da177e4SLinus Torvalds uhci_add_td_to_urb(urb, td); 8751da177e4SLinus Torvalds uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) | 8761da177e4SLinus Torvalds (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), 8771da177e4SLinus Torvalds usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), 8781da177e4SLinus Torvalds data); 8791da177e4SLinus Torvalds 8801da177e4SLinus Torvalds data += pktsze; 8811da177e4SLinus Torvalds len -= maxsze; 8821da177e4SLinus Torvalds 8831da177e4SLinus Torvalds usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), 8841da177e4SLinus Torvalds usb_pipeout(urb->pipe)); 8851da177e4SLinus Torvalds } while (len > 0); 8861da177e4SLinus Torvalds 8871da177e4SLinus Torvalds /* 8881da177e4SLinus Torvalds * URB_ZERO_PACKET means adding a 0-length packet, if direction 8891da177e4SLinus Torvalds * is OUT and the transfer_length was an exact multiple of maxsze, 8901da177e4SLinus Torvalds * hence (len = transfer_length - N * maxsze) == 0 8911da177e4SLinus Torvalds * however, if transfer_length == 0, the zero packet was already 8921da177e4SLinus Torvalds * prepared above. 8931da177e4SLinus Torvalds */ 8941da177e4SLinus Torvalds if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) && 8951da177e4SLinus Torvalds !len && urb->transfer_buffer_length) { 8961da177e4SLinus Torvalds td = uhci_alloc_td(uhci, urb->dev); 8971da177e4SLinus Torvalds if (!td) 8981da177e4SLinus Torvalds return -ENOMEM; 8991da177e4SLinus Torvalds 9001da177e4SLinus Torvalds uhci_add_td_to_urb(urb, td); 9011da177e4SLinus Torvalds uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) | 9021da177e4SLinus Torvalds (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), 9031da177e4SLinus Torvalds usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT), 9041da177e4SLinus Torvalds data); 9051da177e4SLinus Torvalds 9061da177e4SLinus Torvalds usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), 9071da177e4SLinus Torvalds usb_pipeout(urb->pipe)); 9081da177e4SLinus Torvalds } 9091da177e4SLinus Torvalds 9101da177e4SLinus Torvalds /* Set the interrupt-on-completion flag on the last packet. 9111da177e4SLinus Torvalds * A more-or-less typical 4 KB URB (= size of one memory page) 9121da177e4SLinus Torvalds * will require about 3 ms to transfer; that's a little on the 9131da177e4SLinus Torvalds * fast side but not enough to justify delaying an interrupt 9141da177e4SLinus Torvalds * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT 9151da177e4SLinus Torvalds * flag setting. */ 9161da177e4SLinus Torvalds td->status |= cpu_to_le32(TD_CTRL_IOC); 9171da177e4SLinus Torvalds 9181da177e4SLinus Torvalds qh = uhci_alloc_qh(uhci, urb->dev); 9191da177e4SLinus Torvalds if (!qh) 9201da177e4SLinus Torvalds return -ENOMEM; 9211da177e4SLinus Torvalds 9221da177e4SLinus Torvalds urbp->qh = qh; 9231da177e4SLinus Torvalds qh->urbp = urbp; 9241da177e4SLinus Torvalds 9251da177e4SLinus Torvalds /* Always breadth first */ 9261da177e4SLinus Torvalds uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH); 9271da177e4SLinus Torvalds 9281da177e4SLinus Torvalds if (eurb) 9291da177e4SLinus Torvalds uhci_append_queued_urb(uhci, eurb, urb); 9301da177e4SLinus Torvalds else 9311da177e4SLinus Torvalds uhci_insert_qh(uhci, skelqh, urb); 9321da177e4SLinus Torvalds 9331da177e4SLinus Torvalds return -EINPROGRESS; 9341da177e4SLinus Torvalds } 9351da177e4SLinus Torvalds 9361da177e4SLinus Torvalds /* 9371da177e4SLinus Torvalds * Common result for bulk and interrupt 9381da177e4SLinus Torvalds */ 9391da177e4SLinus Torvalds static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) 9401da177e4SLinus Torvalds { 9411da177e4SLinus Torvalds struct urb_priv *urbp = urb->hcpriv; 9421da177e4SLinus Torvalds struct uhci_td *td; 9431da177e4SLinus Torvalds unsigned int status = 0; 9441da177e4SLinus Torvalds int ret = 0; 9451da177e4SLinus Torvalds 9461da177e4SLinus Torvalds urb->actual_length = 0; 9471da177e4SLinus Torvalds 9481da177e4SLinus Torvalds list_for_each_entry(td, &urbp->td_list, list) { 9491da177e4SLinus Torvalds unsigned int ctrlstat = td_status(td); 9501da177e4SLinus Torvalds 9511da177e4SLinus Torvalds status = uhci_status_bits(ctrlstat); 9521da177e4SLinus Torvalds if (status & TD_CTRL_ACTIVE) 9531da177e4SLinus Torvalds return -EINPROGRESS; 9541da177e4SLinus Torvalds 9551da177e4SLinus Torvalds urb->actual_length += uhci_actual_length(ctrlstat); 9561da177e4SLinus Torvalds 9571da177e4SLinus Torvalds if (status) 9581da177e4SLinus Torvalds goto td_error; 9591da177e4SLinus Torvalds 9601da177e4SLinus Torvalds if (uhci_actual_length(ctrlstat) < 9611da177e4SLinus Torvalds uhci_expected_length(td_token(td))) { 9621da177e4SLinus Torvalds if (urb->transfer_flags & URB_SHORT_NOT_OK) { 9631da177e4SLinus Torvalds ret = -EREMOTEIO; 9641da177e4SLinus Torvalds goto err; 9651da177e4SLinus Torvalds } else 9661da177e4SLinus Torvalds return 0; 9671da177e4SLinus Torvalds } 9681da177e4SLinus Torvalds } 9691da177e4SLinus Torvalds 9701da177e4SLinus Torvalds return 0; 9711da177e4SLinus Torvalds 9721da177e4SLinus Torvalds td_error: 9731da177e4SLinus Torvalds ret = uhci_map_status(status, uhci_packetout(td_token(td))); 9741da177e4SLinus Torvalds 9751da177e4SLinus Torvalds err: 9761da177e4SLinus Torvalds /* 9771da177e4SLinus Torvalds * Enable this chunk of code if you want to see some more debugging. 9781da177e4SLinus Torvalds * But be careful, it has the tendancy to starve out khubd and prevent 9791da177e4SLinus Torvalds * disconnects from happening successfully if you have a slow debug 9801da177e4SLinus Torvalds * log interface (like a serial console. 9811da177e4SLinus Torvalds */ 9821da177e4SLinus Torvalds #if 0 9831da177e4SLinus Torvalds if ((debug == 1 && ret != -EPIPE) || debug > 1) { 9841da177e4SLinus Torvalds /* Some debugging code */ 9851da177e4SLinus Torvalds dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", 9861da177e4SLinus Torvalds __FUNCTION__, status); 9871da177e4SLinus Torvalds 9881da177e4SLinus Torvalds if (errbuf) { 9891da177e4SLinus Torvalds /* Print the chain for debugging purposes */ 9901da177e4SLinus Torvalds uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0); 9911da177e4SLinus Torvalds 9921da177e4SLinus Torvalds lprintk(errbuf); 9931da177e4SLinus Torvalds } 9941da177e4SLinus Torvalds } 9951da177e4SLinus Torvalds #endif 9961da177e4SLinus Torvalds return ret; 9971da177e4SLinus Torvalds } 9981da177e4SLinus Torvalds 9991da177e4SLinus Torvalds static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb) 10001da177e4SLinus Torvalds { 10011da177e4SLinus Torvalds int ret; 10021da177e4SLinus Torvalds 10031da177e4SLinus Torvalds /* Can't have low-speed bulk transfers */ 10041da177e4SLinus Torvalds if (urb->dev->speed == USB_SPEED_LOW) 10051da177e4SLinus Torvalds return -EINVAL; 10061da177e4SLinus Torvalds 10071da177e4SLinus Torvalds ret = uhci_submit_common(uhci, urb, eurb, uhci->skel_bulk_qh); 10081da177e4SLinus Torvalds if (ret == -EINPROGRESS) 10091da177e4SLinus Torvalds uhci_inc_fsbr(uhci, urb); 10101da177e4SLinus Torvalds 10111da177e4SLinus Torvalds return ret; 10121da177e4SLinus Torvalds } 10131da177e4SLinus Torvalds 10141da177e4SLinus Torvalds static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb) 10151da177e4SLinus Torvalds { 10161da177e4SLinus Torvalds /* USB 1.1 interrupt transfers only involve one packet per interval; 10171da177e4SLinus Torvalds * that's the uhci_submit_common() "breadth first" policy. Drivers 10181da177e4SLinus Torvalds * can submit urbs of any length, but longer ones might need many 10191da177e4SLinus Torvalds * intervals to complete. 10201da177e4SLinus Torvalds */ 10211da177e4SLinus Torvalds return uhci_submit_common(uhci, urb, eurb, uhci->skelqh[__interval_to_skel(urb->interval)]); 10221da177e4SLinus Torvalds } 10231da177e4SLinus Torvalds 10241da177e4SLinus Torvalds /* 10251da177e4SLinus Torvalds * Isochronous transfers 10261da177e4SLinus Torvalds */ 10271da177e4SLinus Torvalds static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsigned int *start, unsigned int *end) 10281da177e4SLinus Torvalds { 10291da177e4SLinus Torvalds struct urb *last_urb = NULL; 10301da177e4SLinus Torvalds struct urb_priv *up; 10311da177e4SLinus Torvalds int ret = 0; 10321da177e4SLinus Torvalds 10331da177e4SLinus Torvalds list_for_each_entry(up, &uhci->urb_list, urb_list) { 10341da177e4SLinus Torvalds struct urb *u = up->urb; 10351da177e4SLinus Torvalds 10361da177e4SLinus Torvalds /* look for pending URB's with identical pipe handle */ 10371da177e4SLinus Torvalds if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && 10381da177e4SLinus Torvalds (u->status == -EINPROGRESS) && (u != urb)) { 10391da177e4SLinus Torvalds if (!last_urb) 10401da177e4SLinus Torvalds *start = u->start_frame; 10411da177e4SLinus Torvalds last_urb = u; 10421da177e4SLinus Torvalds } 10431da177e4SLinus Torvalds } 10441da177e4SLinus Torvalds 10451da177e4SLinus Torvalds if (last_urb) { 10461da177e4SLinus Torvalds *end = (last_urb->start_frame + last_urb->number_of_packets * 10471da177e4SLinus Torvalds last_urb->interval) & (UHCI_NUMFRAMES-1); 10481da177e4SLinus Torvalds ret = 0; 10491da177e4SLinus Torvalds } else 10501da177e4SLinus Torvalds ret = -1; /* no previous urb found */ 10511da177e4SLinus Torvalds 10521da177e4SLinus Torvalds return ret; 10531da177e4SLinus Torvalds } 10541da177e4SLinus Torvalds 10551da177e4SLinus Torvalds static int isochronous_find_start(struct uhci_hcd *uhci, struct urb *urb) 10561da177e4SLinus Torvalds { 10571da177e4SLinus Torvalds int limits; 10581da177e4SLinus Torvalds unsigned int start = 0, end = 0; 10591da177e4SLinus Torvalds 10601da177e4SLinus Torvalds if (urb->number_of_packets > 900) /* 900? Why? */ 10611da177e4SLinus Torvalds return -EFBIG; 10621da177e4SLinus Torvalds 10631da177e4SLinus Torvalds limits = isochronous_find_limits(uhci, urb, &start, &end); 10641da177e4SLinus Torvalds 10651da177e4SLinus Torvalds if (urb->transfer_flags & URB_ISO_ASAP) { 10661da177e4SLinus Torvalds if (limits) { 10671da177e4SLinus Torvalds uhci_get_current_frame_number(uhci); 10681da177e4SLinus Torvalds urb->start_frame = (uhci->frame_number + 10) 10691da177e4SLinus Torvalds & (UHCI_NUMFRAMES - 1); 10701da177e4SLinus Torvalds } else 10711da177e4SLinus Torvalds urb->start_frame = end; 10721da177e4SLinus Torvalds } else { 10731da177e4SLinus Torvalds urb->start_frame &= (UHCI_NUMFRAMES - 1); 10741da177e4SLinus Torvalds /* FIXME: Sanity check */ 10751da177e4SLinus Torvalds } 10761da177e4SLinus Torvalds 10771da177e4SLinus Torvalds return 0; 10781da177e4SLinus Torvalds } 10791da177e4SLinus Torvalds 10801da177e4SLinus Torvalds /* 10811da177e4SLinus Torvalds * Isochronous transfers 10821da177e4SLinus Torvalds */ 10831da177e4SLinus Torvalds static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb) 10841da177e4SLinus Torvalds { 10851da177e4SLinus Torvalds struct uhci_td *td; 10861da177e4SLinus Torvalds int i, ret, frame; 10871da177e4SLinus Torvalds int status, destination; 10881da177e4SLinus Torvalds 10891da177e4SLinus Torvalds status = TD_CTRL_ACTIVE | TD_CTRL_IOS; 10901da177e4SLinus Torvalds destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); 10911da177e4SLinus Torvalds 10921da177e4SLinus Torvalds ret = isochronous_find_start(uhci, urb); 10931da177e4SLinus Torvalds if (ret) 10941da177e4SLinus Torvalds return ret; 10951da177e4SLinus Torvalds 10961da177e4SLinus Torvalds frame = urb->start_frame; 10971da177e4SLinus Torvalds for (i = 0; i < urb->number_of_packets; i++, frame += urb->interval) { 10981da177e4SLinus Torvalds if (!urb->iso_frame_desc[i].length) 10991da177e4SLinus Torvalds continue; 11001da177e4SLinus Torvalds 11011da177e4SLinus Torvalds td = uhci_alloc_td(uhci, urb->dev); 11021da177e4SLinus Torvalds if (!td) 11031da177e4SLinus Torvalds return -ENOMEM; 11041da177e4SLinus Torvalds 11051da177e4SLinus Torvalds uhci_add_td_to_urb(urb, td); 11061da177e4SLinus Torvalds uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1), 11071da177e4SLinus Torvalds urb->transfer_dma + urb->iso_frame_desc[i].offset); 11081da177e4SLinus Torvalds 11091da177e4SLinus Torvalds if (i + 1 >= urb->number_of_packets) 11101da177e4SLinus Torvalds td->status |= cpu_to_le32(TD_CTRL_IOC); 11111da177e4SLinus Torvalds 11121da177e4SLinus Torvalds uhci_insert_td_frame_list(uhci, td, frame); 11131da177e4SLinus Torvalds } 11141da177e4SLinus Torvalds 11151da177e4SLinus Torvalds return -EINPROGRESS; 11161da177e4SLinus Torvalds } 11171da177e4SLinus Torvalds 11181da177e4SLinus Torvalds static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) 11191da177e4SLinus Torvalds { 11201da177e4SLinus Torvalds struct uhci_td *td; 11211da177e4SLinus Torvalds struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; 11221da177e4SLinus Torvalds int status; 11231da177e4SLinus Torvalds int i, ret = 0; 11241da177e4SLinus Torvalds 11251da177e4SLinus Torvalds urb->actual_length = 0; 11261da177e4SLinus Torvalds 11271da177e4SLinus Torvalds i = 0; 11281da177e4SLinus Torvalds list_for_each_entry(td, &urbp->td_list, list) { 11291da177e4SLinus Torvalds int actlength; 11301da177e4SLinus Torvalds unsigned int ctrlstat = td_status(td); 11311da177e4SLinus Torvalds 11321da177e4SLinus Torvalds if (ctrlstat & TD_CTRL_ACTIVE) 11331da177e4SLinus Torvalds return -EINPROGRESS; 11341da177e4SLinus Torvalds 11351da177e4SLinus Torvalds actlength = uhci_actual_length(ctrlstat); 11361da177e4SLinus Torvalds urb->iso_frame_desc[i].actual_length = actlength; 11371da177e4SLinus Torvalds urb->actual_length += actlength; 11381da177e4SLinus Torvalds 11391da177e4SLinus Torvalds status = uhci_map_status(uhci_status_bits(ctrlstat), 11401da177e4SLinus Torvalds usb_pipeout(urb->pipe)); 11411da177e4SLinus Torvalds urb->iso_frame_desc[i].status = status; 11421da177e4SLinus Torvalds if (status) { 11431da177e4SLinus Torvalds urb->error_count++; 11441da177e4SLinus Torvalds ret = status; 11451da177e4SLinus Torvalds } 11461da177e4SLinus Torvalds 11471da177e4SLinus Torvalds i++; 11481da177e4SLinus Torvalds } 11491da177e4SLinus Torvalds 11501da177e4SLinus Torvalds return ret; 11511da177e4SLinus Torvalds } 11521da177e4SLinus Torvalds 11531da177e4SLinus Torvalds static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb) 11541da177e4SLinus Torvalds { 11551da177e4SLinus Torvalds struct urb_priv *up; 11561da177e4SLinus Torvalds 11571da177e4SLinus Torvalds /* We don't match Isoc transfers since they are special */ 11581da177e4SLinus Torvalds if (usb_pipeisoc(urb->pipe)) 11591da177e4SLinus Torvalds return NULL; 11601da177e4SLinus Torvalds 11611da177e4SLinus Torvalds list_for_each_entry(up, &uhci->urb_list, urb_list) { 11621da177e4SLinus Torvalds struct urb *u = up->urb; 11631da177e4SLinus Torvalds 11641da177e4SLinus Torvalds if (u->dev == urb->dev && u->status == -EINPROGRESS) { 11651da177e4SLinus Torvalds /* For control, ignore the direction */ 11661da177e4SLinus Torvalds if (usb_pipecontrol(urb->pipe) && 11671da177e4SLinus Torvalds (u->pipe & ~USB_DIR_IN) == (urb->pipe & ~USB_DIR_IN)) 11681da177e4SLinus Torvalds return u; 11691da177e4SLinus Torvalds else if (u->pipe == urb->pipe) 11701da177e4SLinus Torvalds return u; 11711da177e4SLinus Torvalds } 11721da177e4SLinus Torvalds } 11731da177e4SLinus Torvalds 11741da177e4SLinus Torvalds return NULL; 11751da177e4SLinus Torvalds } 11761da177e4SLinus Torvalds 11771da177e4SLinus Torvalds static int uhci_urb_enqueue(struct usb_hcd *hcd, 11781da177e4SLinus Torvalds struct usb_host_endpoint *ep, 11791da177e4SLinus Torvalds struct urb *urb, int mem_flags) 11801da177e4SLinus Torvalds { 11811da177e4SLinus Torvalds int ret; 11821da177e4SLinus Torvalds struct uhci_hcd *uhci = hcd_to_uhci(hcd); 11831da177e4SLinus Torvalds unsigned long flags; 11841da177e4SLinus Torvalds struct urb *eurb; 11851da177e4SLinus Torvalds int bustime; 11861da177e4SLinus Torvalds 11871da177e4SLinus Torvalds spin_lock_irqsave(&uhci->lock, flags); 11881da177e4SLinus Torvalds 11891da177e4SLinus Torvalds ret = urb->status; 11901da177e4SLinus Torvalds if (ret != -EINPROGRESS) /* URB already unlinked! */ 11911da177e4SLinus Torvalds goto out; 11921da177e4SLinus Torvalds 11931da177e4SLinus Torvalds eurb = uhci_find_urb_ep(uhci, urb); 11941da177e4SLinus Torvalds 11951da177e4SLinus Torvalds if (!uhci_alloc_urb_priv(uhci, urb)) { 11961da177e4SLinus Torvalds ret = -ENOMEM; 11971da177e4SLinus Torvalds goto out; 11981da177e4SLinus Torvalds } 11991da177e4SLinus Torvalds 12001da177e4SLinus Torvalds switch (usb_pipetype(urb->pipe)) { 12011da177e4SLinus Torvalds case PIPE_CONTROL: 12021da177e4SLinus Torvalds ret = uhci_submit_control(uhci, urb, eurb); 12031da177e4SLinus Torvalds break; 12041da177e4SLinus Torvalds case PIPE_INTERRUPT: 12051da177e4SLinus Torvalds if (!eurb) { 12061da177e4SLinus Torvalds bustime = usb_check_bandwidth(urb->dev, urb); 12071da177e4SLinus Torvalds if (bustime < 0) 12081da177e4SLinus Torvalds ret = bustime; 12091da177e4SLinus Torvalds else { 12101da177e4SLinus Torvalds ret = uhci_submit_interrupt(uhci, urb, eurb); 12111da177e4SLinus Torvalds if (ret == -EINPROGRESS) 12121da177e4SLinus Torvalds usb_claim_bandwidth(urb->dev, urb, bustime, 0); 12131da177e4SLinus Torvalds } 12141da177e4SLinus Torvalds } else { /* inherit from parent */ 12151da177e4SLinus Torvalds urb->bandwidth = eurb->bandwidth; 12161da177e4SLinus Torvalds ret = uhci_submit_interrupt(uhci, urb, eurb); 12171da177e4SLinus Torvalds } 12181da177e4SLinus Torvalds break; 12191da177e4SLinus Torvalds case PIPE_BULK: 12201da177e4SLinus Torvalds ret = uhci_submit_bulk(uhci, urb, eurb); 12211da177e4SLinus Torvalds break; 12221da177e4SLinus Torvalds case PIPE_ISOCHRONOUS: 12231da177e4SLinus Torvalds bustime = usb_check_bandwidth(urb->dev, urb); 12241da177e4SLinus Torvalds if (bustime < 0) { 12251da177e4SLinus Torvalds ret = bustime; 12261da177e4SLinus Torvalds break; 12271da177e4SLinus Torvalds } 12281da177e4SLinus Torvalds 12291da177e4SLinus Torvalds ret = uhci_submit_isochronous(uhci, urb); 12301da177e4SLinus Torvalds if (ret == -EINPROGRESS) 12311da177e4SLinus Torvalds usb_claim_bandwidth(urb->dev, urb, bustime, 1); 12321da177e4SLinus Torvalds break; 12331da177e4SLinus Torvalds } 12341da177e4SLinus Torvalds 12351da177e4SLinus Torvalds if (ret != -EINPROGRESS) { 12361da177e4SLinus Torvalds /* Submit failed, so delete it from the urb_list */ 12371da177e4SLinus Torvalds struct urb_priv *urbp = urb->hcpriv; 12381da177e4SLinus Torvalds 12391da177e4SLinus Torvalds list_del_init(&urbp->urb_list); 12401da177e4SLinus Torvalds uhci_destroy_urb_priv(uhci, urb); 12411da177e4SLinus Torvalds } else 12421da177e4SLinus Torvalds ret = 0; 12431da177e4SLinus Torvalds 12441da177e4SLinus Torvalds out: 12451da177e4SLinus Torvalds spin_unlock_irqrestore(&uhci->lock, flags); 12461da177e4SLinus Torvalds return ret; 12471da177e4SLinus Torvalds } 12481da177e4SLinus Torvalds 12491da177e4SLinus Torvalds /* 12501da177e4SLinus Torvalds * Return the result of a transfer 12511da177e4SLinus Torvalds */ 12521da177e4SLinus Torvalds static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb) 12531da177e4SLinus Torvalds { 12541da177e4SLinus Torvalds int ret = -EINPROGRESS; 12551da177e4SLinus Torvalds struct urb_priv *urbp; 12561da177e4SLinus Torvalds 12571da177e4SLinus Torvalds spin_lock(&urb->lock); 12581da177e4SLinus Torvalds 12591da177e4SLinus Torvalds urbp = (struct urb_priv *)urb->hcpriv; 12601da177e4SLinus Torvalds 12611da177e4SLinus Torvalds if (urb->status != -EINPROGRESS) /* URB already dequeued */ 12621da177e4SLinus Torvalds goto out; 12631da177e4SLinus Torvalds 12641da177e4SLinus Torvalds switch (usb_pipetype(urb->pipe)) { 12651da177e4SLinus Torvalds case PIPE_CONTROL: 12661da177e4SLinus Torvalds ret = uhci_result_control(uhci, urb); 12671da177e4SLinus Torvalds break; 12681da177e4SLinus Torvalds case PIPE_BULK: 12691da177e4SLinus Torvalds case PIPE_INTERRUPT: 12701da177e4SLinus Torvalds ret = uhci_result_common(uhci, urb); 12711da177e4SLinus Torvalds break; 12721da177e4SLinus Torvalds case PIPE_ISOCHRONOUS: 12731da177e4SLinus Torvalds ret = uhci_result_isochronous(uhci, urb); 12741da177e4SLinus Torvalds break; 12751da177e4SLinus Torvalds } 12761da177e4SLinus Torvalds 12771da177e4SLinus Torvalds if (ret == -EINPROGRESS) 12781da177e4SLinus Torvalds goto out; 12791da177e4SLinus Torvalds urb->status = ret; 12801da177e4SLinus Torvalds 12811da177e4SLinus Torvalds switch (usb_pipetype(urb->pipe)) { 12821da177e4SLinus Torvalds case PIPE_CONTROL: 12831da177e4SLinus Torvalds case PIPE_BULK: 12841da177e4SLinus Torvalds case PIPE_ISOCHRONOUS: 12851da177e4SLinus Torvalds /* Release bandwidth for Interrupt or Isoc. transfers */ 12861da177e4SLinus Torvalds if (urb->bandwidth) 12871da177e4SLinus Torvalds usb_release_bandwidth(urb->dev, urb, 1); 12881da177e4SLinus Torvalds uhci_unlink_generic(uhci, urb); 12891da177e4SLinus Torvalds break; 12901da177e4SLinus Torvalds case PIPE_INTERRUPT: 12911da177e4SLinus Torvalds /* Release bandwidth for Interrupt or Isoc. transfers */ 12921da177e4SLinus Torvalds /* Make sure we don't release if we have a queued URB */ 12931da177e4SLinus Torvalds if (list_empty(&urbp->queue_list) && urb->bandwidth) 12941da177e4SLinus Torvalds usb_release_bandwidth(urb->dev, urb, 0); 12951da177e4SLinus Torvalds else 12961da177e4SLinus Torvalds /* bandwidth was passed on to queued URB, */ 12971da177e4SLinus Torvalds /* so don't let usb_unlink_urb() release it */ 12981da177e4SLinus Torvalds urb->bandwidth = 0; 12991da177e4SLinus Torvalds uhci_unlink_generic(uhci, urb); 13001da177e4SLinus Torvalds break; 13011da177e4SLinus Torvalds default: 13021da177e4SLinus Torvalds dev_info(uhci_dev(uhci), "%s: unknown pipe type %d " 13031da177e4SLinus Torvalds "for urb %p\n", 13041da177e4SLinus Torvalds __FUNCTION__, usb_pipetype(urb->pipe), urb); 13051da177e4SLinus Torvalds } 13061da177e4SLinus Torvalds 13071da177e4SLinus Torvalds /* Move it from uhci->urb_list to uhci->complete_list */ 13081da177e4SLinus Torvalds uhci_moveto_complete(uhci, urbp); 13091da177e4SLinus Torvalds 13101da177e4SLinus Torvalds out: 13111da177e4SLinus Torvalds spin_unlock(&urb->lock); 13121da177e4SLinus Torvalds } 13131da177e4SLinus Torvalds 13141da177e4SLinus Torvalds static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb) 13151da177e4SLinus Torvalds { 13161da177e4SLinus Torvalds struct list_head *head; 13171da177e4SLinus Torvalds struct uhci_td *td; 13181da177e4SLinus Torvalds struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; 13191da177e4SLinus Torvalds int prevactive = 0; 13201da177e4SLinus Torvalds 13211da177e4SLinus Torvalds uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ 13221da177e4SLinus Torvalds 13231da177e4SLinus Torvalds /* 13241da177e4SLinus Torvalds * Now we need to find out what the last successful toggle was 13251da177e4SLinus Torvalds * so we can update the local data toggle for the next transfer 13261da177e4SLinus Torvalds * 13271da177e4SLinus Torvalds * There are 2 ways the last successful completed TD is found: 13281da177e4SLinus Torvalds * 13291da177e4SLinus Torvalds * 1) The TD is NOT active and the actual length < expected length 13301da177e4SLinus Torvalds * 2) The TD is NOT active and it's the last TD in the chain 13311da177e4SLinus Torvalds * 13321da177e4SLinus Torvalds * and a third way the first uncompleted TD is found: 13331da177e4SLinus Torvalds * 13341da177e4SLinus Torvalds * 3) The TD is active and the previous TD is NOT active 13351da177e4SLinus Torvalds * 13361da177e4SLinus Torvalds * Control and Isochronous ignore the toggle, so this is safe 13371da177e4SLinus Torvalds * for all types 13381da177e4SLinus Torvalds * 13391da177e4SLinus Torvalds * FIXME: The toggle fixups won't be 100% reliable until we 13401da177e4SLinus Torvalds * change over to using a single queue for each endpoint and 13411da177e4SLinus Torvalds * stop the queue before unlinking. 13421da177e4SLinus Torvalds */ 13431da177e4SLinus Torvalds head = &urbp->td_list; 13441da177e4SLinus Torvalds list_for_each_entry(td, head, list) { 13451da177e4SLinus Torvalds unsigned int ctrlstat = td_status(td); 13461da177e4SLinus Torvalds 13471da177e4SLinus Torvalds if (!(ctrlstat & TD_CTRL_ACTIVE) && 13481da177e4SLinus Torvalds (uhci_actual_length(ctrlstat) < 13491da177e4SLinus Torvalds uhci_expected_length(td_token(td)) || 13501da177e4SLinus Torvalds td->list.next == head)) 13511da177e4SLinus Torvalds usb_settoggle(urb->dev, uhci_endpoint(td_token(td)), 13521da177e4SLinus Torvalds uhci_packetout(td_token(td)), 13531da177e4SLinus Torvalds uhci_toggle(td_token(td)) ^ 1); 13541da177e4SLinus Torvalds else if ((ctrlstat & TD_CTRL_ACTIVE) && !prevactive) 13551da177e4SLinus Torvalds usb_settoggle(urb->dev, uhci_endpoint(td_token(td)), 13561da177e4SLinus Torvalds uhci_packetout(td_token(td)), 13571da177e4SLinus Torvalds uhci_toggle(td_token(td))); 13581da177e4SLinus Torvalds 13591da177e4SLinus Torvalds prevactive = ctrlstat & TD_CTRL_ACTIVE; 13601da177e4SLinus Torvalds } 13611da177e4SLinus Torvalds 13621da177e4SLinus Torvalds uhci_delete_queued_urb(uhci, urb); 13631da177e4SLinus Torvalds 13641da177e4SLinus Torvalds /* The interrupt loop will reclaim the QH's */ 13651da177e4SLinus Torvalds uhci_remove_qh(uhci, urbp->qh); 13661da177e4SLinus Torvalds urbp->qh = NULL; 13671da177e4SLinus Torvalds } 13681da177e4SLinus Torvalds 13691da177e4SLinus Torvalds static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) 13701da177e4SLinus Torvalds { 13711da177e4SLinus Torvalds struct uhci_hcd *uhci = hcd_to_uhci(hcd); 13721da177e4SLinus Torvalds unsigned long flags; 13731da177e4SLinus Torvalds struct urb_priv *urbp; 13741da177e4SLinus Torvalds 13751da177e4SLinus Torvalds spin_lock_irqsave(&uhci->lock, flags); 13761da177e4SLinus Torvalds urbp = urb->hcpriv; 13771da177e4SLinus Torvalds if (!urbp) /* URB was never linked! */ 13781da177e4SLinus Torvalds goto done; 13791da177e4SLinus Torvalds list_del_init(&urbp->urb_list); 13801da177e4SLinus Torvalds 13811da177e4SLinus Torvalds uhci_unlink_generic(uhci, urb); 13821da177e4SLinus Torvalds 13831da177e4SLinus Torvalds uhci_get_current_frame_number(uhci); 13841da177e4SLinus Torvalds if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age) { 13851da177e4SLinus Torvalds uhci_remove_pending_urbps(uhci); 13861da177e4SLinus Torvalds uhci->urb_remove_age = uhci->frame_number; 13871da177e4SLinus Torvalds } 13881da177e4SLinus Torvalds 13891da177e4SLinus Torvalds /* If we're the first, set the next interrupt bit */ 13901da177e4SLinus Torvalds if (list_empty(&uhci->urb_remove_list)) 13911da177e4SLinus Torvalds uhci_set_next_interrupt(uhci); 13921da177e4SLinus Torvalds list_add_tail(&urbp->urb_list, &uhci->urb_remove_list); 13931da177e4SLinus Torvalds 13941da177e4SLinus Torvalds done: 13951da177e4SLinus Torvalds spin_unlock_irqrestore(&uhci->lock, flags); 13961da177e4SLinus Torvalds return 0; 13971da177e4SLinus Torvalds } 13981da177e4SLinus Torvalds 13991da177e4SLinus Torvalds static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb) 14001da177e4SLinus Torvalds { 14011da177e4SLinus Torvalds struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; 14021da177e4SLinus Torvalds struct list_head *head; 14031da177e4SLinus Torvalds struct uhci_td *td; 14041da177e4SLinus Torvalds int count = 0; 14051da177e4SLinus Torvalds 14061da177e4SLinus Torvalds uhci_dec_fsbr(uhci, urb); 14071da177e4SLinus Torvalds 14081da177e4SLinus Torvalds urbp->fsbr_timeout = 1; 14091da177e4SLinus Torvalds 14101da177e4SLinus Torvalds /* 14111da177e4SLinus Torvalds * Ideally we would want to fix qh->element as well, but it's 14121da177e4SLinus Torvalds * read/write by the HC, so that can introduce a race. It's not 14131da177e4SLinus Torvalds * really worth the hassle 14141da177e4SLinus Torvalds */ 14151da177e4SLinus Torvalds 14161da177e4SLinus Torvalds head = &urbp->td_list; 14171da177e4SLinus Torvalds list_for_each_entry(td, head, list) { 14181da177e4SLinus Torvalds /* 14191da177e4SLinus Torvalds * Make sure we don't do the last one (since it'll have the 14201da177e4SLinus Torvalds * TERM bit set) as well as we skip every so many TD's to 14211da177e4SLinus Torvalds * make sure it doesn't hog the bandwidth 14221da177e4SLinus Torvalds */ 14231da177e4SLinus Torvalds if (td->list.next != head && (count % DEPTH_INTERVAL) == 14241da177e4SLinus Torvalds (DEPTH_INTERVAL - 1)) 14251da177e4SLinus Torvalds td->link |= UHCI_PTR_DEPTH; 14261da177e4SLinus Torvalds 14271da177e4SLinus Torvalds count++; 14281da177e4SLinus Torvalds } 14291da177e4SLinus Torvalds 14301da177e4SLinus Torvalds return 0; 14311da177e4SLinus Torvalds } 14321da177e4SLinus Torvalds 14331da177e4SLinus Torvalds static void uhci_free_pending_qhs(struct uhci_hcd *uhci) 14341da177e4SLinus Torvalds { 14351da177e4SLinus Torvalds struct uhci_qh *qh, *tmp; 14361da177e4SLinus Torvalds 14371da177e4SLinus Torvalds list_for_each_entry_safe(qh, tmp, &uhci->qh_remove_list, remove_list) { 14381da177e4SLinus Torvalds list_del_init(&qh->remove_list); 14391da177e4SLinus Torvalds 14401da177e4SLinus Torvalds uhci_free_qh(uhci, qh); 14411da177e4SLinus Torvalds } 14421da177e4SLinus Torvalds } 14431da177e4SLinus Torvalds 14441da177e4SLinus Torvalds static void uhci_free_pending_tds(struct uhci_hcd *uhci) 14451da177e4SLinus Torvalds { 14461da177e4SLinus Torvalds struct uhci_td *td, *tmp; 14471da177e4SLinus Torvalds 14481da177e4SLinus Torvalds list_for_each_entry_safe(td, tmp, &uhci->td_remove_list, remove_list) { 14491da177e4SLinus Torvalds list_del_init(&td->remove_list); 14501da177e4SLinus Torvalds 14511da177e4SLinus Torvalds uhci_free_td(uhci, td); 14521da177e4SLinus Torvalds } 14531da177e4SLinus Torvalds } 14541da177e4SLinus Torvalds 14551da177e4SLinus Torvalds static void 14561da177e4SLinus Torvalds uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs) 14571da177e4SLinus Torvalds __releases(uhci->lock) 14581da177e4SLinus Torvalds __acquires(uhci->lock) 14591da177e4SLinus Torvalds { 14601da177e4SLinus Torvalds struct uhci_hcd *uhci = hcd_to_uhci(hcd); 14611da177e4SLinus Torvalds 14621da177e4SLinus Torvalds uhci_destroy_urb_priv(uhci, urb); 14631da177e4SLinus Torvalds 14641da177e4SLinus Torvalds spin_unlock(&uhci->lock); 14651da177e4SLinus Torvalds usb_hcd_giveback_urb(hcd, urb, regs); 14661da177e4SLinus Torvalds spin_lock(&uhci->lock); 14671da177e4SLinus Torvalds } 14681da177e4SLinus Torvalds 14691da177e4SLinus Torvalds static void uhci_finish_completion(struct uhci_hcd *uhci, struct pt_regs *regs) 14701da177e4SLinus Torvalds { 14711da177e4SLinus Torvalds struct urb_priv *urbp, *tmp; 14721da177e4SLinus Torvalds 14731da177e4SLinus Torvalds list_for_each_entry_safe(urbp, tmp, &uhci->complete_list, urb_list) { 14741da177e4SLinus Torvalds struct urb *urb = urbp->urb; 14751da177e4SLinus Torvalds 14761da177e4SLinus Torvalds list_del_init(&urbp->urb_list); 14771da177e4SLinus Torvalds uhci_finish_urb(uhci_to_hcd(uhci), urb, regs); 14781da177e4SLinus Torvalds } 14791da177e4SLinus Torvalds } 14801da177e4SLinus Torvalds 14811da177e4SLinus Torvalds static void uhci_remove_pending_urbps(struct uhci_hcd *uhci) 14821da177e4SLinus Torvalds { 14831da177e4SLinus Torvalds 14841da177e4SLinus Torvalds /* Splice the urb_remove_list onto the end of the complete_list */ 14851da177e4SLinus Torvalds list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev); 14861da177e4SLinus Torvalds } 14871da177e4SLinus Torvalds 14881da177e4SLinus Torvalds /* Process events in the schedule, but only in one thread at a time */ 14891da177e4SLinus Torvalds static void uhci_scan_schedule(struct uhci_hcd *uhci, struct pt_regs *regs) 14901da177e4SLinus Torvalds { 14911da177e4SLinus Torvalds struct urb_priv *urbp, *tmp; 14921da177e4SLinus Torvalds 14931da177e4SLinus Torvalds /* Don't allow re-entrant calls */ 14941da177e4SLinus Torvalds if (uhci->scan_in_progress) { 14951da177e4SLinus Torvalds uhci->need_rescan = 1; 14961da177e4SLinus Torvalds return; 14971da177e4SLinus Torvalds } 14981da177e4SLinus Torvalds uhci->scan_in_progress = 1; 14991da177e4SLinus Torvalds rescan: 15001da177e4SLinus Torvalds uhci->need_rescan = 0; 15011da177e4SLinus Torvalds 1502*6c1b445cSAlan Stern uhci_clear_next_interrupt(uhci); 15031da177e4SLinus Torvalds uhci_get_current_frame_number(uhci); 15041da177e4SLinus Torvalds 15051da177e4SLinus Torvalds if (uhci->frame_number + uhci->is_stopped != uhci->qh_remove_age) 15061da177e4SLinus Torvalds uhci_free_pending_qhs(uhci); 15071da177e4SLinus Torvalds if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) 15081da177e4SLinus Torvalds uhci_free_pending_tds(uhci); 15091da177e4SLinus Torvalds if (uhci->frame_number + uhci->is_stopped != uhci->urb_remove_age) 15101da177e4SLinus Torvalds uhci_remove_pending_urbps(uhci); 15111da177e4SLinus Torvalds 15121da177e4SLinus Torvalds /* Walk the list of pending URBs to see which ones completed 15131da177e4SLinus Torvalds * (must be _safe because uhci_transfer_result() dequeues URBs) */ 15141da177e4SLinus Torvalds list_for_each_entry_safe(urbp, tmp, &uhci->urb_list, urb_list) { 15151da177e4SLinus Torvalds struct urb *urb = urbp->urb; 15161da177e4SLinus Torvalds 15171da177e4SLinus Torvalds /* Checks the status and does all of the magic necessary */ 15181da177e4SLinus Torvalds uhci_transfer_result(uhci, urb); 15191da177e4SLinus Torvalds } 15201da177e4SLinus Torvalds uhci_finish_completion(uhci, regs); 15211da177e4SLinus Torvalds 15221da177e4SLinus Torvalds /* If the controller is stopped, we can finish these off right now */ 15231da177e4SLinus Torvalds if (uhci->is_stopped) { 15241da177e4SLinus Torvalds uhci_free_pending_qhs(uhci); 15251da177e4SLinus Torvalds uhci_free_pending_tds(uhci); 15261da177e4SLinus Torvalds uhci_remove_pending_urbps(uhci); 15271da177e4SLinus Torvalds } 15281da177e4SLinus Torvalds 15291da177e4SLinus Torvalds if (uhci->need_rescan) 15301da177e4SLinus Torvalds goto rescan; 15311da177e4SLinus Torvalds uhci->scan_in_progress = 0; 15321da177e4SLinus Torvalds 15331da177e4SLinus Torvalds if (list_empty(&uhci->urb_remove_list) && 15341da177e4SLinus Torvalds list_empty(&uhci->td_remove_list) && 15351da177e4SLinus Torvalds list_empty(&uhci->qh_remove_list)) 15361da177e4SLinus Torvalds uhci_clear_next_interrupt(uhci); 15371da177e4SLinus Torvalds else 15381da177e4SLinus Torvalds uhci_set_next_interrupt(uhci); 15391da177e4SLinus Torvalds 15401da177e4SLinus Torvalds /* Wake up anyone waiting for an URB to complete */ 15411da177e4SLinus Torvalds wake_up_all(&uhci->waitqh); 15421da177e4SLinus Torvalds } 1543f5946f82SAlan Stern 1544f5946f82SAlan Stern static void check_fsbr(struct uhci_hcd *uhci) 1545f5946f82SAlan Stern { 1546f5946f82SAlan Stern struct urb_priv *up; 1547f5946f82SAlan Stern 1548f5946f82SAlan Stern list_for_each_entry(up, &uhci->urb_list, urb_list) { 1549f5946f82SAlan Stern struct urb *u = up->urb; 1550f5946f82SAlan Stern 1551f5946f82SAlan Stern spin_lock(&u->lock); 1552f5946f82SAlan Stern 1553f5946f82SAlan Stern /* Check if the FSBR timed out */ 1554f5946f82SAlan Stern if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT)) 1555f5946f82SAlan Stern uhci_fsbr_timeout(uhci, u); 1556f5946f82SAlan Stern 1557f5946f82SAlan Stern spin_unlock(&u->lock); 1558f5946f82SAlan Stern } 1559f5946f82SAlan Stern 1560f5946f82SAlan Stern /* Really disable FSBR */ 1561f5946f82SAlan Stern if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) { 1562f5946f82SAlan Stern uhci->fsbrtimeout = 0; 1563f5946f82SAlan Stern uhci->skel_term_qh->link = UHCI_PTR_TERM; 1564f5946f82SAlan Stern } 1565f5946f82SAlan Stern } 1566