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