162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Universal Host Controller Interface driver for USB. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Maintainer: Alan Stern <stern@rowland.harvard.edu> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * (C) Copyright 1999 Linus Torvalds 862306a36Sopenharmony_ci * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com 962306a36Sopenharmony_ci * (C) Copyright 1999 Randy Dunlap 1062306a36Sopenharmony_ci * (C) Copyright 1999 Georg Acher, acher@in.tum.de 1162306a36Sopenharmony_ci * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de 1262306a36Sopenharmony_ci * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch 1362306a36Sopenharmony_ci * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at 1462306a36Sopenharmony_ci * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface 1562306a36Sopenharmony_ci * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). 1662306a36Sopenharmony_ci * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) 1762306a36Sopenharmony_ci * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* 2262306a36Sopenharmony_ci * Technically, updating td->status here is a race, but it's not really a 2362306a36Sopenharmony_ci * problem. The worst that can happen is that we set the IOC bit again 2462306a36Sopenharmony_ci * generating a spurious interrupt. We could fix this by creating another 2562306a36Sopenharmony_ci * QH and leaving the IOC bit always set, but then we would have to play 2662306a36Sopenharmony_ci * games with the FSBR code to make sure we get the correct order in all 2762306a36Sopenharmony_ci * the cases. I don't think it's worth the effort 2862306a36Sopenharmony_ci */ 2962306a36Sopenharmony_cistatic void uhci_set_next_interrupt(struct uhci_hcd *uhci) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci if (uhci->is_stopped) 3262306a36Sopenharmony_ci mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); 3362306a36Sopenharmony_ci uhci->term_td->status |= cpu_to_hc32(uhci, TD_CTRL_IOC); 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci uhci->term_td->status &= ~cpu_to_hc32(uhci, TD_CTRL_IOC); 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* 4362306a36Sopenharmony_ci * Full-Speed Bandwidth Reclamation (FSBR). 4462306a36Sopenharmony_ci * We turn on FSBR whenever a queue that wants it is advancing, 4562306a36Sopenharmony_ci * and leave it on for a short time thereafter. 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_cistatic void uhci_fsbr_on(struct uhci_hcd *uhci) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci struct uhci_qh *lqh; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci /* The terminating skeleton QH always points back to the first 5262306a36Sopenharmony_ci * FSBR QH. Make the last async QH point to the terminating 5362306a36Sopenharmony_ci * skeleton QH. */ 5462306a36Sopenharmony_ci uhci->fsbr_is_on = 1; 5562306a36Sopenharmony_ci lqh = list_entry(uhci->skel_async_qh->node.prev, 5662306a36Sopenharmony_ci struct uhci_qh, node); 5762306a36Sopenharmony_ci lqh->link = LINK_TO_QH(uhci, uhci->skel_term_qh); 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic void uhci_fsbr_off(struct uhci_hcd *uhci) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci struct uhci_qh *lqh; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci /* Remove the link from the last async QH to the terminating 6562306a36Sopenharmony_ci * skeleton QH. */ 6662306a36Sopenharmony_ci uhci->fsbr_is_on = 0; 6762306a36Sopenharmony_ci lqh = list_entry(uhci->skel_async_qh->node.prev, 6862306a36Sopenharmony_ci struct uhci_qh, node); 6962306a36Sopenharmony_ci lqh->link = UHCI_PTR_TERM(uhci); 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci struct urb_priv *urbp = urb->hcpriv; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci urbp->fsbr = 1; 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic void uhci_urbp_wants_fsbr(struct uhci_hcd *uhci, struct urb_priv *urbp) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci if (urbp->fsbr) { 8262306a36Sopenharmony_ci uhci->fsbr_is_wanted = 1; 8362306a36Sopenharmony_ci if (!uhci->fsbr_is_on) 8462306a36Sopenharmony_ci uhci_fsbr_on(uhci); 8562306a36Sopenharmony_ci else if (uhci->fsbr_expiring) { 8662306a36Sopenharmony_ci uhci->fsbr_expiring = 0; 8762306a36Sopenharmony_ci del_timer(&uhci->fsbr_timer); 8862306a36Sopenharmony_ci } 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic void uhci_fsbr_timeout(struct timer_list *t) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci struct uhci_hcd *uhci = from_timer(uhci, t, fsbr_timer); 9562306a36Sopenharmony_ci unsigned long flags; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci spin_lock_irqsave(&uhci->lock, flags); 9862306a36Sopenharmony_ci if (uhci->fsbr_expiring) { 9962306a36Sopenharmony_ci uhci->fsbr_expiring = 0; 10062306a36Sopenharmony_ci uhci_fsbr_off(uhci); 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci spin_unlock_irqrestore(&uhci->lock, flags); 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci dma_addr_t dma_handle; 10962306a36Sopenharmony_ci struct uhci_td *td; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci td = dma_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle); 11262306a36Sopenharmony_ci if (!td) 11362306a36Sopenharmony_ci return NULL; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci td->dma_handle = dma_handle; 11662306a36Sopenharmony_ci td->frame = -1; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci INIT_LIST_HEAD(&td->list); 11962306a36Sopenharmony_ci INIT_LIST_HEAD(&td->fl_list); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci return td; 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci if (!list_empty(&td->list)) 12762306a36Sopenharmony_ci dev_WARN(uhci_dev(uhci), "td %p still in list!\n", td); 12862306a36Sopenharmony_ci if (!list_empty(&td->fl_list)) 12962306a36Sopenharmony_ci dev_WARN(uhci_dev(uhci), "td %p still in fl_list!\n", td); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci dma_pool_free(uhci->td_pool, td, td->dma_handle); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic inline void uhci_fill_td(struct uhci_hcd *uhci, struct uhci_td *td, 13562306a36Sopenharmony_ci u32 status, u32 token, u32 buffer) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci td->status = cpu_to_hc32(uhci, status); 13862306a36Sopenharmony_ci td->token = cpu_to_hc32(uhci, token); 13962306a36Sopenharmony_ci td->buffer = cpu_to_hc32(uhci, buffer); 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic void uhci_add_td_to_urbp(struct uhci_td *td, struct urb_priv *urbp) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci list_add_tail(&td->list, &urbp->td_list); 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic void uhci_remove_td_from_urbp(struct uhci_td *td) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci list_del_init(&td->list); 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci/* 15362306a36Sopenharmony_ci * We insert Isochronous URBs directly into the frame list at the beginning 15462306a36Sopenharmony_ci */ 15562306a36Sopenharmony_cistatic inline void uhci_insert_td_in_frame_list(struct uhci_hcd *uhci, 15662306a36Sopenharmony_ci struct uhci_td *td, unsigned framenum) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci framenum &= (UHCI_NUMFRAMES - 1); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci td->frame = framenum; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci /* Is there a TD already mapped there? */ 16362306a36Sopenharmony_ci if (uhci->frame_cpu[framenum]) { 16462306a36Sopenharmony_ci struct uhci_td *ftd, *ltd; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci ftd = uhci->frame_cpu[framenum]; 16762306a36Sopenharmony_ci ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci list_add_tail(&td->fl_list, &ftd->fl_list); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci td->link = ltd->link; 17262306a36Sopenharmony_ci wmb(); 17362306a36Sopenharmony_ci ltd->link = LINK_TO_TD(uhci, td); 17462306a36Sopenharmony_ci } else { 17562306a36Sopenharmony_ci td->link = uhci->frame[framenum]; 17662306a36Sopenharmony_ci wmb(); 17762306a36Sopenharmony_ci uhci->frame[framenum] = LINK_TO_TD(uhci, td); 17862306a36Sopenharmony_ci uhci->frame_cpu[framenum] = td; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic inline void uhci_remove_td_from_frame_list(struct uhci_hcd *uhci, 18362306a36Sopenharmony_ci struct uhci_td *td) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci /* If it's not inserted, don't remove it */ 18662306a36Sopenharmony_ci if (td->frame == -1) { 18762306a36Sopenharmony_ci WARN_ON(!list_empty(&td->fl_list)); 18862306a36Sopenharmony_ci return; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci if (uhci->frame_cpu[td->frame] == td) { 19262306a36Sopenharmony_ci if (list_empty(&td->fl_list)) { 19362306a36Sopenharmony_ci uhci->frame[td->frame] = td->link; 19462306a36Sopenharmony_ci uhci->frame_cpu[td->frame] = NULL; 19562306a36Sopenharmony_ci } else { 19662306a36Sopenharmony_ci struct uhci_td *ntd; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci ntd = list_entry(td->fl_list.next, 19962306a36Sopenharmony_ci struct uhci_td, 20062306a36Sopenharmony_ci fl_list); 20162306a36Sopenharmony_ci uhci->frame[td->frame] = LINK_TO_TD(uhci, ntd); 20262306a36Sopenharmony_ci uhci->frame_cpu[td->frame] = ntd; 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci } else { 20562306a36Sopenharmony_ci struct uhci_td *ptd; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list); 20862306a36Sopenharmony_ci ptd->link = td->link; 20962306a36Sopenharmony_ci } 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci list_del_init(&td->fl_list); 21262306a36Sopenharmony_ci td->frame = -1; 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic inline void uhci_remove_tds_from_frame(struct uhci_hcd *uhci, 21662306a36Sopenharmony_ci unsigned int framenum) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci struct uhci_td *ftd, *ltd; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci framenum &= (UHCI_NUMFRAMES - 1); 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci ftd = uhci->frame_cpu[framenum]; 22362306a36Sopenharmony_ci if (ftd) { 22462306a36Sopenharmony_ci ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list); 22562306a36Sopenharmony_ci uhci->frame[framenum] = ltd->link; 22662306a36Sopenharmony_ci uhci->frame_cpu[framenum] = NULL; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci while (!list_empty(&ftd->fl_list)) 22962306a36Sopenharmony_ci list_del_init(ftd->fl_list.prev); 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci/* 23462306a36Sopenharmony_ci * Remove all the TDs for an Isochronous URB from the frame list 23562306a36Sopenharmony_ci */ 23662306a36Sopenharmony_cistatic void uhci_unlink_isochronous_tds(struct uhci_hcd *uhci, struct urb *urb) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; 23962306a36Sopenharmony_ci struct uhci_td *td; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci list_for_each_entry(td, &urbp->td_list, list) 24262306a36Sopenharmony_ci uhci_remove_td_from_frame_list(uhci, td); 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cistatic struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, 24662306a36Sopenharmony_ci struct usb_device *udev, struct usb_host_endpoint *hep) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci dma_addr_t dma_handle; 24962306a36Sopenharmony_ci struct uhci_qh *qh; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci qh = dma_pool_zalloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); 25262306a36Sopenharmony_ci if (!qh) 25362306a36Sopenharmony_ci return NULL; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci qh->dma_handle = dma_handle; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci qh->element = UHCI_PTR_TERM(uhci); 25862306a36Sopenharmony_ci qh->link = UHCI_PTR_TERM(uhci); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci INIT_LIST_HEAD(&qh->queue); 26162306a36Sopenharmony_ci INIT_LIST_HEAD(&qh->node); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci if (udev) { /* Normal QH */ 26462306a36Sopenharmony_ci qh->type = usb_endpoint_type(&hep->desc); 26562306a36Sopenharmony_ci if (qh->type != USB_ENDPOINT_XFER_ISOC) { 26662306a36Sopenharmony_ci qh->dummy_td = uhci_alloc_td(uhci); 26762306a36Sopenharmony_ci if (!qh->dummy_td) { 26862306a36Sopenharmony_ci dma_pool_free(uhci->qh_pool, qh, dma_handle); 26962306a36Sopenharmony_ci return NULL; 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci qh->state = QH_STATE_IDLE; 27362306a36Sopenharmony_ci qh->hep = hep; 27462306a36Sopenharmony_ci qh->udev = udev; 27562306a36Sopenharmony_ci hep->hcpriv = qh; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci if (qh->type == USB_ENDPOINT_XFER_INT || 27862306a36Sopenharmony_ci qh->type == USB_ENDPOINT_XFER_ISOC) 27962306a36Sopenharmony_ci qh->load = usb_calc_bus_time(udev->speed, 28062306a36Sopenharmony_ci usb_endpoint_dir_in(&hep->desc), 28162306a36Sopenharmony_ci qh->type == USB_ENDPOINT_XFER_ISOC, 28262306a36Sopenharmony_ci usb_endpoint_maxp(&hep->desc)) 28362306a36Sopenharmony_ci / 1000 + 1; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci } else { /* Skeleton QH */ 28662306a36Sopenharmony_ci qh->state = QH_STATE_ACTIVE; 28762306a36Sopenharmony_ci qh->type = -1; 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci return qh; 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) 29362306a36Sopenharmony_ci{ 29462306a36Sopenharmony_ci WARN_ON(qh->state != QH_STATE_IDLE && qh->udev); 29562306a36Sopenharmony_ci if (!list_empty(&qh->queue)) 29662306a36Sopenharmony_ci dev_WARN(uhci_dev(uhci), "qh %p list not empty!\n", qh); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci list_del(&qh->node); 29962306a36Sopenharmony_ci if (qh->udev) { 30062306a36Sopenharmony_ci qh->hep->hcpriv = NULL; 30162306a36Sopenharmony_ci if (qh->dummy_td) 30262306a36Sopenharmony_ci uhci_free_td(uhci, qh->dummy_td); 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci/* 30862306a36Sopenharmony_ci * When a queue is stopped and a dequeued URB is given back, adjust 30962306a36Sopenharmony_ci * the previous TD link (if the URB isn't first on the queue) or 31062306a36Sopenharmony_ci * save its toggle value (if it is first and is currently executing). 31162306a36Sopenharmony_ci * 31262306a36Sopenharmony_ci * Returns 0 if the URB should not yet be given back, 1 otherwise. 31362306a36Sopenharmony_ci */ 31462306a36Sopenharmony_cistatic int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh, 31562306a36Sopenharmony_ci struct urb *urb) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci struct urb_priv *urbp = urb->hcpriv; 31862306a36Sopenharmony_ci struct uhci_td *td; 31962306a36Sopenharmony_ci int ret = 1; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci /* Isochronous pipes don't use toggles and their TD link pointers 32262306a36Sopenharmony_ci * get adjusted during uhci_urb_dequeue(). But since their queues 32362306a36Sopenharmony_ci * cannot truly be stopped, we have to watch out for dequeues 32462306a36Sopenharmony_ci * occurring after the nominal unlink frame. */ 32562306a36Sopenharmony_ci if (qh->type == USB_ENDPOINT_XFER_ISOC) { 32662306a36Sopenharmony_ci ret = (uhci->frame_number + uhci->is_stopped != 32762306a36Sopenharmony_ci qh->unlink_frame); 32862306a36Sopenharmony_ci goto done; 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci /* If the URB isn't first on its queue, adjust the link pointer 33262306a36Sopenharmony_ci * of the last TD in the previous URB. The toggle doesn't need 33362306a36Sopenharmony_ci * to be saved since this URB can't be executing yet. */ 33462306a36Sopenharmony_ci if (qh->queue.next != &urbp->node) { 33562306a36Sopenharmony_ci struct urb_priv *purbp; 33662306a36Sopenharmony_ci struct uhci_td *ptd; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci purbp = list_entry(urbp->node.prev, struct urb_priv, node); 33962306a36Sopenharmony_ci WARN_ON(list_empty(&purbp->td_list)); 34062306a36Sopenharmony_ci ptd = list_entry(purbp->td_list.prev, struct uhci_td, 34162306a36Sopenharmony_ci list); 34262306a36Sopenharmony_ci td = list_entry(urbp->td_list.prev, struct uhci_td, 34362306a36Sopenharmony_ci list); 34462306a36Sopenharmony_ci ptd->link = td->link; 34562306a36Sopenharmony_ci goto done; 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci /* If the QH element pointer is UHCI_PTR_TERM then then currently 34962306a36Sopenharmony_ci * executing URB has already been unlinked, so this one isn't it. */ 35062306a36Sopenharmony_ci if (qh_element(qh) == UHCI_PTR_TERM(uhci)) 35162306a36Sopenharmony_ci goto done; 35262306a36Sopenharmony_ci qh->element = UHCI_PTR_TERM(uhci); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci /* Control pipes don't have to worry about toggles */ 35562306a36Sopenharmony_ci if (qh->type == USB_ENDPOINT_XFER_CONTROL) 35662306a36Sopenharmony_ci goto done; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci /* Save the next toggle value */ 35962306a36Sopenharmony_ci WARN_ON(list_empty(&urbp->td_list)); 36062306a36Sopenharmony_ci td = list_entry(urbp->td_list.next, struct uhci_td, list); 36162306a36Sopenharmony_ci qh->needs_fixup = 1; 36262306a36Sopenharmony_ci qh->initial_toggle = uhci_toggle(td_token(uhci, td)); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_cidone: 36562306a36Sopenharmony_ci return ret; 36662306a36Sopenharmony_ci} 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci/* 36962306a36Sopenharmony_ci * Fix up the data toggles for URBs in a queue, when one of them 37062306a36Sopenharmony_ci * terminates early (short transfer, error, or dequeued). 37162306a36Sopenharmony_ci */ 37262306a36Sopenharmony_cistatic void uhci_fixup_toggles(struct uhci_hcd *uhci, struct uhci_qh *qh, 37362306a36Sopenharmony_ci int skip_first) 37462306a36Sopenharmony_ci{ 37562306a36Sopenharmony_ci struct urb_priv *urbp = NULL; 37662306a36Sopenharmony_ci struct uhci_td *td; 37762306a36Sopenharmony_ci unsigned int toggle = qh->initial_toggle; 37862306a36Sopenharmony_ci unsigned int pipe; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci /* Fixups for a short transfer start with the second URB in the 38162306a36Sopenharmony_ci * queue (the short URB is the first). */ 38262306a36Sopenharmony_ci if (skip_first) 38362306a36Sopenharmony_ci urbp = list_entry(qh->queue.next, struct urb_priv, node); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci /* When starting with the first URB, if the QH element pointer is 38662306a36Sopenharmony_ci * still valid then we know the URB's toggles are okay. */ 38762306a36Sopenharmony_ci else if (qh_element(qh) != UHCI_PTR_TERM(uhci)) 38862306a36Sopenharmony_ci toggle = 2; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci /* Fix up the toggle for the URBs in the queue. Normally this 39162306a36Sopenharmony_ci * loop won't run more than once: When an error or short transfer 39262306a36Sopenharmony_ci * occurs, the queue usually gets emptied. */ 39362306a36Sopenharmony_ci urbp = list_prepare_entry(urbp, &qh->queue, node); 39462306a36Sopenharmony_ci list_for_each_entry_continue(urbp, &qh->queue, node) { 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci /* If the first TD has the right toggle value, we don't 39762306a36Sopenharmony_ci * need to change any toggles in this URB */ 39862306a36Sopenharmony_ci td = list_entry(urbp->td_list.next, struct uhci_td, list); 39962306a36Sopenharmony_ci if (toggle > 1 || uhci_toggle(td_token(uhci, td)) == toggle) { 40062306a36Sopenharmony_ci td = list_entry(urbp->td_list.prev, struct uhci_td, 40162306a36Sopenharmony_ci list); 40262306a36Sopenharmony_ci toggle = uhci_toggle(td_token(uhci, td)) ^ 1; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci /* Otherwise all the toggles in the URB have to be switched */ 40562306a36Sopenharmony_ci } else { 40662306a36Sopenharmony_ci list_for_each_entry(td, &urbp->td_list, list) { 40762306a36Sopenharmony_ci td->token ^= cpu_to_hc32(uhci, 40862306a36Sopenharmony_ci TD_TOKEN_TOGGLE); 40962306a36Sopenharmony_ci toggle ^= 1; 41062306a36Sopenharmony_ci } 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci } 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci wmb(); 41562306a36Sopenharmony_ci pipe = list_entry(qh->queue.next, struct urb_priv, node)->urb->pipe; 41662306a36Sopenharmony_ci usb_settoggle(qh->udev, usb_pipeendpoint(pipe), 41762306a36Sopenharmony_ci usb_pipeout(pipe), toggle); 41862306a36Sopenharmony_ci qh->needs_fixup = 0; 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci/* 42262306a36Sopenharmony_ci * Link an Isochronous QH into its skeleton's list 42362306a36Sopenharmony_ci */ 42462306a36Sopenharmony_cistatic inline void link_iso(struct uhci_hcd *uhci, struct uhci_qh *qh) 42562306a36Sopenharmony_ci{ 42662306a36Sopenharmony_ci list_add_tail(&qh->node, &uhci->skel_iso_qh->node); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci /* Isochronous QHs aren't linked by the hardware */ 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci/* 43262306a36Sopenharmony_ci * Link a high-period interrupt QH into the schedule at the end of its 43362306a36Sopenharmony_ci * skeleton's list 43462306a36Sopenharmony_ci */ 43562306a36Sopenharmony_cistatic void link_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci struct uhci_qh *pqh; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci list_add_tail(&qh->node, &uhci->skelqh[qh->skel]->node); 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci pqh = list_entry(qh->node.prev, struct uhci_qh, node); 44262306a36Sopenharmony_ci qh->link = pqh->link; 44362306a36Sopenharmony_ci wmb(); 44462306a36Sopenharmony_ci pqh->link = LINK_TO_QH(uhci, qh); 44562306a36Sopenharmony_ci} 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci/* 44862306a36Sopenharmony_ci * Link a period-1 interrupt or async QH into the schedule at the 44962306a36Sopenharmony_ci * correct spot in the async skeleton's list, and update the FSBR link 45062306a36Sopenharmony_ci */ 45162306a36Sopenharmony_cistatic void link_async(struct uhci_hcd *uhci, struct uhci_qh *qh) 45262306a36Sopenharmony_ci{ 45362306a36Sopenharmony_ci struct uhci_qh *pqh; 45462306a36Sopenharmony_ci __hc32 link_to_new_qh; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci /* Find the predecessor QH for our new one and insert it in the list. 45762306a36Sopenharmony_ci * The list of QHs is expected to be short, so linear search won't 45862306a36Sopenharmony_ci * take too long. */ 45962306a36Sopenharmony_ci list_for_each_entry_reverse(pqh, &uhci->skel_async_qh->node, node) { 46062306a36Sopenharmony_ci if (pqh->skel <= qh->skel) 46162306a36Sopenharmony_ci break; 46262306a36Sopenharmony_ci } 46362306a36Sopenharmony_ci list_add(&qh->node, &pqh->node); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci /* Link it into the schedule */ 46662306a36Sopenharmony_ci qh->link = pqh->link; 46762306a36Sopenharmony_ci wmb(); 46862306a36Sopenharmony_ci link_to_new_qh = LINK_TO_QH(uhci, qh); 46962306a36Sopenharmony_ci pqh->link = link_to_new_qh; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci /* If this is now the first FSBR QH, link the terminating skeleton 47262306a36Sopenharmony_ci * QH to it. */ 47362306a36Sopenharmony_ci if (pqh->skel < SKEL_FSBR && qh->skel >= SKEL_FSBR) 47462306a36Sopenharmony_ci uhci->skel_term_qh->link = link_to_new_qh; 47562306a36Sopenharmony_ci} 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci/* 47862306a36Sopenharmony_ci * Put a QH on the schedule in both hardware and software 47962306a36Sopenharmony_ci */ 48062306a36Sopenharmony_cistatic void uhci_activate_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) 48162306a36Sopenharmony_ci{ 48262306a36Sopenharmony_ci WARN_ON(list_empty(&qh->queue)); 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci /* Set the element pointer if it isn't set already. 48562306a36Sopenharmony_ci * This isn't needed for Isochronous queues, but it doesn't hurt. */ 48662306a36Sopenharmony_ci if (qh_element(qh) == UHCI_PTR_TERM(uhci)) { 48762306a36Sopenharmony_ci struct urb_priv *urbp = list_entry(qh->queue.next, 48862306a36Sopenharmony_ci struct urb_priv, node); 48962306a36Sopenharmony_ci struct uhci_td *td = list_entry(urbp->td_list.next, 49062306a36Sopenharmony_ci struct uhci_td, list); 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci qh->element = LINK_TO_TD(uhci, td); 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci /* Treat the queue as if it has just advanced */ 49662306a36Sopenharmony_ci qh->wait_expired = 0; 49762306a36Sopenharmony_ci qh->advance_jiffies = jiffies; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci if (qh->state == QH_STATE_ACTIVE) 50062306a36Sopenharmony_ci return; 50162306a36Sopenharmony_ci qh->state = QH_STATE_ACTIVE; 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci /* Move the QH from its old list to the correct spot in the appropriate 50462306a36Sopenharmony_ci * skeleton's list */ 50562306a36Sopenharmony_ci if (qh == uhci->next_qh) 50662306a36Sopenharmony_ci uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, 50762306a36Sopenharmony_ci node); 50862306a36Sopenharmony_ci list_del(&qh->node); 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci if (qh->skel == SKEL_ISO) 51162306a36Sopenharmony_ci link_iso(uhci, qh); 51262306a36Sopenharmony_ci else if (qh->skel < SKEL_ASYNC) 51362306a36Sopenharmony_ci link_interrupt(uhci, qh); 51462306a36Sopenharmony_ci else 51562306a36Sopenharmony_ci link_async(uhci, qh); 51662306a36Sopenharmony_ci} 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci/* 51962306a36Sopenharmony_ci * Unlink a high-period interrupt QH from the schedule 52062306a36Sopenharmony_ci */ 52162306a36Sopenharmony_cistatic void unlink_interrupt(struct uhci_hcd *uhci, struct uhci_qh *qh) 52262306a36Sopenharmony_ci{ 52362306a36Sopenharmony_ci struct uhci_qh *pqh; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci pqh = list_entry(qh->node.prev, struct uhci_qh, node); 52662306a36Sopenharmony_ci pqh->link = qh->link; 52762306a36Sopenharmony_ci mb(); 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci/* 53162306a36Sopenharmony_ci * Unlink a period-1 interrupt or async QH from the schedule 53262306a36Sopenharmony_ci */ 53362306a36Sopenharmony_cistatic void unlink_async(struct uhci_hcd *uhci, struct uhci_qh *qh) 53462306a36Sopenharmony_ci{ 53562306a36Sopenharmony_ci struct uhci_qh *pqh; 53662306a36Sopenharmony_ci __hc32 link_to_next_qh = qh->link; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci pqh = list_entry(qh->node.prev, struct uhci_qh, node); 53962306a36Sopenharmony_ci pqh->link = link_to_next_qh; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci /* If this was the old first FSBR QH, link the terminating skeleton 54262306a36Sopenharmony_ci * QH to the next (new first FSBR) QH. */ 54362306a36Sopenharmony_ci if (pqh->skel < SKEL_FSBR && qh->skel >= SKEL_FSBR) 54462306a36Sopenharmony_ci uhci->skel_term_qh->link = link_to_next_qh; 54562306a36Sopenharmony_ci mb(); 54662306a36Sopenharmony_ci} 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci/* 54962306a36Sopenharmony_ci * Take a QH off the hardware schedule 55062306a36Sopenharmony_ci */ 55162306a36Sopenharmony_cistatic void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) 55262306a36Sopenharmony_ci{ 55362306a36Sopenharmony_ci if (qh->state == QH_STATE_UNLINKING) 55462306a36Sopenharmony_ci return; 55562306a36Sopenharmony_ci WARN_ON(qh->state != QH_STATE_ACTIVE || !qh->udev); 55662306a36Sopenharmony_ci qh->state = QH_STATE_UNLINKING; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci /* Unlink the QH from the schedule and record when we did it */ 55962306a36Sopenharmony_ci if (qh->skel == SKEL_ISO) 56062306a36Sopenharmony_ci ; 56162306a36Sopenharmony_ci else if (qh->skel < SKEL_ASYNC) 56262306a36Sopenharmony_ci unlink_interrupt(uhci, qh); 56362306a36Sopenharmony_ci else 56462306a36Sopenharmony_ci unlink_async(uhci, qh); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci uhci_get_current_frame_number(uhci); 56762306a36Sopenharmony_ci qh->unlink_frame = uhci->frame_number; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci /* Force an interrupt so we know when the QH is fully unlinked */ 57062306a36Sopenharmony_ci if (list_empty(&uhci->skel_unlink_qh->node) || uhci->is_stopped) 57162306a36Sopenharmony_ci uhci_set_next_interrupt(uhci); 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci /* Move the QH from its old list to the end of the unlinking list */ 57462306a36Sopenharmony_ci if (qh == uhci->next_qh) 57562306a36Sopenharmony_ci uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, 57662306a36Sopenharmony_ci node); 57762306a36Sopenharmony_ci list_move_tail(&qh->node, &uhci->skel_unlink_qh->node); 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci/* 58162306a36Sopenharmony_ci * When we and the controller are through with a QH, it becomes IDLE. 58262306a36Sopenharmony_ci * This happens when a QH has been off the schedule (on the unlinking 58362306a36Sopenharmony_ci * list) for more than one frame, or when an error occurs while adding 58462306a36Sopenharmony_ci * the first URB onto a new QH. 58562306a36Sopenharmony_ci */ 58662306a36Sopenharmony_cistatic void uhci_make_qh_idle(struct uhci_hcd *uhci, struct uhci_qh *qh) 58762306a36Sopenharmony_ci{ 58862306a36Sopenharmony_ci WARN_ON(qh->state == QH_STATE_ACTIVE); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci if (qh == uhci->next_qh) 59162306a36Sopenharmony_ci uhci->next_qh = list_entry(qh->node.next, struct uhci_qh, 59262306a36Sopenharmony_ci node); 59362306a36Sopenharmony_ci list_move(&qh->node, &uhci->idle_qh_list); 59462306a36Sopenharmony_ci qh->state = QH_STATE_IDLE; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci /* Now that the QH is idle, its post_td isn't being used */ 59762306a36Sopenharmony_ci if (qh->post_td) { 59862306a36Sopenharmony_ci uhci_free_td(uhci, qh->post_td); 59962306a36Sopenharmony_ci qh->post_td = NULL; 60062306a36Sopenharmony_ci } 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci /* If anyone is waiting for a QH to become idle, wake them up */ 60362306a36Sopenharmony_ci if (uhci->num_waiting) 60462306a36Sopenharmony_ci wake_up_all(&uhci->waitqh); 60562306a36Sopenharmony_ci} 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci/* 60862306a36Sopenharmony_ci * Find the highest existing bandwidth load for a given phase and period. 60962306a36Sopenharmony_ci */ 61062306a36Sopenharmony_cistatic int uhci_highest_load(struct uhci_hcd *uhci, int phase, int period) 61162306a36Sopenharmony_ci{ 61262306a36Sopenharmony_ci int highest_load = uhci->load[phase]; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci for (phase += period; phase < MAX_PHASE; phase += period) 61562306a36Sopenharmony_ci highest_load = max_t(int, highest_load, uhci->load[phase]); 61662306a36Sopenharmony_ci return highest_load; 61762306a36Sopenharmony_ci} 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci/* 62062306a36Sopenharmony_ci * Set qh->phase to the optimal phase for a periodic transfer and 62162306a36Sopenharmony_ci * check whether the bandwidth requirement is acceptable. 62262306a36Sopenharmony_ci */ 62362306a36Sopenharmony_cistatic int uhci_check_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh) 62462306a36Sopenharmony_ci{ 62562306a36Sopenharmony_ci int minimax_load; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci /* Find the optimal phase (unless it is already set) and get 62862306a36Sopenharmony_ci * its load value. */ 62962306a36Sopenharmony_ci if (qh->phase >= 0) 63062306a36Sopenharmony_ci minimax_load = uhci_highest_load(uhci, qh->phase, qh->period); 63162306a36Sopenharmony_ci else { 63262306a36Sopenharmony_ci int phase, load; 63362306a36Sopenharmony_ci int max_phase = min_t(int, MAX_PHASE, qh->period); 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci qh->phase = 0; 63662306a36Sopenharmony_ci minimax_load = uhci_highest_load(uhci, qh->phase, qh->period); 63762306a36Sopenharmony_ci for (phase = 1; phase < max_phase; ++phase) { 63862306a36Sopenharmony_ci load = uhci_highest_load(uhci, phase, qh->period); 63962306a36Sopenharmony_ci if (load < minimax_load) { 64062306a36Sopenharmony_ci minimax_load = load; 64162306a36Sopenharmony_ci qh->phase = phase; 64262306a36Sopenharmony_ci } 64362306a36Sopenharmony_ci } 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci /* Maximum allowable periodic bandwidth is 90%, or 900 us per frame */ 64762306a36Sopenharmony_ci if (minimax_load + qh->load > 900) { 64862306a36Sopenharmony_ci dev_dbg(uhci_dev(uhci), "bandwidth allocation failed: " 64962306a36Sopenharmony_ci "period %d, phase %d, %d + %d us\n", 65062306a36Sopenharmony_ci qh->period, qh->phase, minimax_load, qh->load); 65162306a36Sopenharmony_ci return -ENOSPC; 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci return 0; 65462306a36Sopenharmony_ci} 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci/* 65762306a36Sopenharmony_ci * Reserve a periodic QH's bandwidth in the schedule 65862306a36Sopenharmony_ci */ 65962306a36Sopenharmony_cistatic void uhci_reserve_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh) 66062306a36Sopenharmony_ci{ 66162306a36Sopenharmony_ci int i; 66262306a36Sopenharmony_ci int load = qh->load; 66362306a36Sopenharmony_ci char *p = "??"; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci for (i = qh->phase; i < MAX_PHASE; i += qh->period) { 66662306a36Sopenharmony_ci uhci->load[i] += load; 66762306a36Sopenharmony_ci uhci->total_load += load; 66862306a36Sopenharmony_ci } 66962306a36Sopenharmony_ci uhci_to_hcd(uhci)->self.bandwidth_allocated = 67062306a36Sopenharmony_ci uhci->total_load / MAX_PHASE; 67162306a36Sopenharmony_ci switch (qh->type) { 67262306a36Sopenharmony_ci case USB_ENDPOINT_XFER_INT: 67362306a36Sopenharmony_ci ++uhci_to_hcd(uhci)->self.bandwidth_int_reqs; 67462306a36Sopenharmony_ci p = "INT"; 67562306a36Sopenharmony_ci break; 67662306a36Sopenharmony_ci case USB_ENDPOINT_XFER_ISOC: 67762306a36Sopenharmony_ci ++uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs; 67862306a36Sopenharmony_ci p = "ISO"; 67962306a36Sopenharmony_ci break; 68062306a36Sopenharmony_ci } 68162306a36Sopenharmony_ci qh->bandwidth_reserved = 1; 68262306a36Sopenharmony_ci dev_dbg(uhci_dev(uhci), 68362306a36Sopenharmony_ci "%s dev %d ep%02x-%s, period %d, phase %d, %d us\n", 68462306a36Sopenharmony_ci "reserve", qh->udev->devnum, 68562306a36Sopenharmony_ci qh->hep->desc.bEndpointAddress, p, 68662306a36Sopenharmony_ci qh->period, qh->phase, load); 68762306a36Sopenharmony_ci} 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci/* 69062306a36Sopenharmony_ci * Release a periodic QH's bandwidth reservation 69162306a36Sopenharmony_ci */ 69262306a36Sopenharmony_cistatic void uhci_release_bandwidth(struct uhci_hcd *uhci, struct uhci_qh *qh) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci int i; 69562306a36Sopenharmony_ci int load = qh->load; 69662306a36Sopenharmony_ci char *p = "??"; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci for (i = qh->phase; i < MAX_PHASE; i += qh->period) { 69962306a36Sopenharmony_ci uhci->load[i] -= load; 70062306a36Sopenharmony_ci uhci->total_load -= load; 70162306a36Sopenharmony_ci } 70262306a36Sopenharmony_ci uhci_to_hcd(uhci)->self.bandwidth_allocated = 70362306a36Sopenharmony_ci uhci->total_load / MAX_PHASE; 70462306a36Sopenharmony_ci switch (qh->type) { 70562306a36Sopenharmony_ci case USB_ENDPOINT_XFER_INT: 70662306a36Sopenharmony_ci --uhci_to_hcd(uhci)->self.bandwidth_int_reqs; 70762306a36Sopenharmony_ci p = "INT"; 70862306a36Sopenharmony_ci break; 70962306a36Sopenharmony_ci case USB_ENDPOINT_XFER_ISOC: 71062306a36Sopenharmony_ci --uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs; 71162306a36Sopenharmony_ci p = "ISO"; 71262306a36Sopenharmony_ci break; 71362306a36Sopenharmony_ci } 71462306a36Sopenharmony_ci qh->bandwidth_reserved = 0; 71562306a36Sopenharmony_ci dev_dbg(uhci_dev(uhci), 71662306a36Sopenharmony_ci "%s dev %d ep%02x-%s, period %d, phase %d, %d us\n", 71762306a36Sopenharmony_ci "release", qh->udev->devnum, 71862306a36Sopenharmony_ci qh->hep->desc.bEndpointAddress, p, 71962306a36Sopenharmony_ci qh->period, qh->phase, load); 72062306a36Sopenharmony_ci} 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_cistatic inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, 72362306a36Sopenharmony_ci struct urb *urb) 72462306a36Sopenharmony_ci{ 72562306a36Sopenharmony_ci struct urb_priv *urbp; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci urbp = kmem_cache_zalloc(uhci_up_cachep, GFP_ATOMIC); 72862306a36Sopenharmony_ci if (!urbp) 72962306a36Sopenharmony_ci return NULL; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci urbp->urb = urb; 73262306a36Sopenharmony_ci urb->hcpriv = urbp; 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci INIT_LIST_HEAD(&urbp->node); 73562306a36Sopenharmony_ci INIT_LIST_HEAD(&urbp->td_list); 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci return urbp; 73862306a36Sopenharmony_ci} 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_cistatic void uhci_free_urb_priv(struct uhci_hcd *uhci, 74162306a36Sopenharmony_ci struct urb_priv *urbp) 74262306a36Sopenharmony_ci{ 74362306a36Sopenharmony_ci struct uhci_td *td, *tmp; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci if (!list_empty(&urbp->node)) 74662306a36Sopenharmony_ci dev_WARN(uhci_dev(uhci), "urb %p still on QH's list!\n", 74762306a36Sopenharmony_ci urbp->urb); 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { 75062306a36Sopenharmony_ci uhci_remove_td_from_urbp(td); 75162306a36Sopenharmony_ci uhci_free_td(uhci, td); 75262306a36Sopenharmony_ci } 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci kmem_cache_free(uhci_up_cachep, urbp); 75562306a36Sopenharmony_ci} 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci/* 75862306a36Sopenharmony_ci * Map status to standard result codes 75962306a36Sopenharmony_ci * 76062306a36Sopenharmony_ci * <status> is (td_status(uhci, td) & 0xF60000), a.k.a. 76162306a36Sopenharmony_ci * uhci_status_bits(td_status(uhci, td)). 76262306a36Sopenharmony_ci * Note: <status> does not include the TD_CTRL_NAK bit. 76362306a36Sopenharmony_ci * <dir_out> is True for output TDs and False for input TDs. 76462306a36Sopenharmony_ci */ 76562306a36Sopenharmony_cistatic int uhci_map_status(int status, int dir_out) 76662306a36Sopenharmony_ci{ 76762306a36Sopenharmony_ci if (!status) 76862306a36Sopenharmony_ci return 0; 76962306a36Sopenharmony_ci if (status & TD_CTRL_BITSTUFF) /* Bitstuff error */ 77062306a36Sopenharmony_ci return -EPROTO; 77162306a36Sopenharmony_ci if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */ 77262306a36Sopenharmony_ci if (dir_out) 77362306a36Sopenharmony_ci return -EPROTO; 77462306a36Sopenharmony_ci else 77562306a36Sopenharmony_ci return -EILSEQ; 77662306a36Sopenharmony_ci } 77762306a36Sopenharmony_ci if (status & TD_CTRL_BABBLE) /* Babble */ 77862306a36Sopenharmony_ci return -EOVERFLOW; 77962306a36Sopenharmony_ci if (status & TD_CTRL_DBUFERR) /* Buffer error */ 78062306a36Sopenharmony_ci return -ENOSR; 78162306a36Sopenharmony_ci if (status & TD_CTRL_STALLED) /* Stalled */ 78262306a36Sopenharmony_ci return -EPIPE; 78362306a36Sopenharmony_ci return 0; 78462306a36Sopenharmony_ci} 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci/* 78762306a36Sopenharmony_ci * Control transfers 78862306a36Sopenharmony_ci */ 78962306a36Sopenharmony_cistatic int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, 79062306a36Sopenharmony_ci struct uhci_qh *qh) 79162306a36Sopenharmony_ci{ 79262306a36Sopenharmony_ci struct uhci_td *td; 79362306a36Sopenharmony_ci unsigned long destination, status; 79462306a36Sopenharmony_ci int maxsze = usb_endpoint_maxp(&qh->hep->desc); 79562306a36Sopenharmony_ci int len = urb->transfer_buffer_length; 79662306a36Sopenharmony_ci dma_addr_t data = urb->transfer_dma; 79762306a36Sopenharmony_ci __hc32 *plink; 79862306a36Sopenharmony_ci struct urb_priv *urbp = urb->hcpriv; 79962306a36Sopenharmony_ci int skel; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci /* The "pipe" thing contains the destination in bits 8--18 */ 80262306a36Sopenharmony_ci destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci /* 3 errors, dummy TD remains inactive */ 80562306a36Sopenharmony_ci status = uhci_maxerr(3); 80662306a36Sopenharmony_ci if (urb->dev->speed == USB_SPEED_LOW) 80762306a36Sopenharmony_ci status |= TD_CTRL_LS; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci /* 81062306a36Sopenharmony_ci * Build the TD for the control request setup packet 81162306a36Sopenharmony_ci */ 81262306a36Sopenharmony_ci td = qh->dummy_td; 81362306a36Sopenharmony_ci uhci_add_td_to_urbp(td, urbp); 81462306a36Sopenharmony_ci uhci_fill_td(uhci, td, status, destination | uhci_explen(8), 81562306a36Sopenharmony_ci urb->setup_dma); 81662306a36Sopenharmony_ci plink = &td->link; 81762306a36Sopenharmony_ci status |= TD_CTRL_ACTIVE; 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci /* 82062306a36Sopenharmony_ci * If direction is "send", change the packet ID from SETUP (0x2D) 82162306a36Sopenharmony_ci * to OUT (0xE1). Else change it from SETUP to IN (0x69) and 82262306a36Sopenharmony_ci * set Short Packet Detect (SPD) for all data packets. 82362306a36Sopenharmony_ci * 82462306a36Sopenharmony_ci * 0-length transfers always get treated as "send". 82562306a36Sopenharmony_ci */ 82662306a36Sopenharmony_ci if (usb_pipeout(urb->pipe) || len == 0) 82762306a36Sopenharmony_ci destination ^= (USB_PID_SETUP ^ USB_PID_OUT); 82862306a36Sopenharmony_ci else { 82962306a36Sopenharmony_ci destination ^= (USB_PID_SETUP ^ USB_PID_IN); 83062306a36Sopenharmony_ci status |= TD_CTRL_SPD; 83162306a36Sopenharmony_ci } 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci /* 83462306a36Sopenharmony_ci * Build the DATA TDs 83562306a36Sopenharmony_ci */ 83662306a36Sopenharmony_ci while (len > 0) { 83762306a36Sopenharmony_ci int pktsze = maxsze; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci if (len <= pktsze) { /* The last data packet */ 84062306a36Sopenharmony_ci pktsze = len; 84162306a36Sopenharmony_ci status &= ~TD_CTRL_SPD; 84262306a36Sopenharmony_ci } 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci td = uhci_alloc_td(uhci); 84562306a36Sopenharmony_ci if (!td) 84662306a36Sopenharmony_ci goto nomem; 84762306a36Sopenharmony_ci *plink = LINK_TO_TD(uhci, td); 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci /* Alternate Data0/1 (start with Data1) */ 85062306a36Sopenharmony_ci destination ^= TD_TOKEN_TOGGLE; 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci uhci_add_td_to_urbp(td, urbp); 85362306a36Sopenharmony_ci uhci_fill_td(uhci, td, status, 85462306a36Sopenharmony_ci destination | uhci_explen(pktsze), data); 85562306a36Sopenharmony_ci plink = &td->link; 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci data += pktsze; 85862306a36Sopenharmony_ci len -= pktsze; 85962306a36Sopenharmony_ci } 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci /* 86262306a36Sopenharmony_ci * Build the final TD for control status 86362306a36Sopenharmony_ci */ 86462306a36Sopenharmony_ci td = uhci_alloc_td(uhci); 86562306a36Sopenharmony_ci if (!td) 86662306a36Sopenharmony_ci goto nomem; 86762306a36Sopenharmony_ci *plink = LINK_TO_TD(uhci, td); 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci /* Change direction for the status transaction */ 87062306a36Sopenharmony_ci destination ^= (USB_PID_IN ^ USB_PID_OUT); 87162306a36Sopenharmony_ci destination |= TD_TOKEN_TOGGLE; /* End in Data1 */ 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_ci uhci_add_td_to_urbp(td, urbp); 87462306a36Sopenharmony_ci uhci_fill_td(uhci, td, status | TD_CTRL_IOC, 87562306a36Sopenharmony_ci destination | uhci_explen(0), 0); 87662306a36Sopenharmony_ci plink = &td->link; 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci /* 87962306a36Sopenharmony_ci * Build the new dummy TD and activate the old one 88062306a36Sopenharmony_ci */ 88162306a36Sopenharmony_ci td = uhci_alloc_td(uhci); 88262306a36Sopenharmony_ci if (!td) 88362306a36Sopenharmony_ci goto nomem; 88462306a36Sopenharmony_ci *plink = LINK_TO_TD(uhci, td); 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci uhci_fill_td(uhci, td, 0, USB_PID_OUT | uhci_explen(0), 0); 88762306a36Sopenharmony_ci wmb(); 88862306a36Sopenharmony_ci qh->dummy_td->status |= cpu_to_hc32(uhci, TD_CTRL_ACTIVE); 88962306a36Sopenharmony_ci qh->dummy_td = td; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci /* Low-speed transfers get a different queue, and won't hog the bus. 89262306a36Sopenharmony_ci * Also, some devices enumerate better without FSBR; the easiest way 89362306a36Sopenharmony_ci * to do that is to put URBs on the low-speed queue while the device 89462306a36Sopenharmony_ci * isn't in the CONFIGURED state. */ 89562306a36Sopenharmony_ci if (urb->dev->speed == USB_SPEED_LOW || 89662306a36Sopenharmony_ci urb->dev->state != USB_STATE_CONFIGURED) 89762306a36Sopenharmony_ci skel = SKEL_LS_CONTROL; 89862306a36Sopenharmony_ci else { 89962306a36Sopenharmony_ci skel = SKEL_FS_CONTROL; 90062306a36Sopenharmony_ci uhci_add_fsbr(uhci, urb); 90162306a36Sopenharmony_ci } 90262306a36Sopenharmony_ci if (qh->state != QH_STATE_ACTIVE) 90362306a36Sopenharmony_ci qh->skel = skel; 90462306a36Sopenharmony_ci return 0; 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_cinomem: 90762306a36Sopenharmony_ci /* Remove the dummy TD from the td_list so it doesn't get freed */ 90862306a36Sopenharmony_ci uhci_remove_td_from_urbp(qh->dummy_td); 90962306a36Sopenharmony_ci return -ENOMEM; 91062306a36Sopenharmony_ci} 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci/* 91362306a36Sopenharmony_ci * Common submit for bulk and interrupt 91462306a36Sopenharmony_ci */ 91562306a36Sopenharmony_cistatic int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, 91662306a36Sopenharmony_ci struct uhci_qh *qh) 91762306a36Sopenharmony_ci{ 91862306a36Sopenharmony_ci struct uhci_td *td; 91962306a36Sopenharmony_ci unsigned long destination, status; 92062306a36Sopenharmony_ci int maxsze = usb_endpoint_maxp(&qh->hep->desc); 92162306a36Sopenharmony_ci int len = urb->transfer_buffer_length; 92262306a36Sopenharmony_ci int this_sg_len; 92362306a36Sopenharmony_ci dma_addr_t data; 92462306a36Sopenharmony_ci __hc32 *plink; 92562306a36Sopenharmony_ci struct urb_priv *urbp = urb->hcpriv; 92662306a36Sopenharmony_ci unsigned int toggle; 92762306a36Sopenharmony_ci struct scatterlist *sg; 92862306a36Sopenharmony_ci int i; 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci if (len < 0) 93162306a36Sopenharmony_ci return -EINVAL; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci /* The "pipe" thing contains the destination in bits 8--18 */ 93462306a36Sopenharmony_ci destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); 93562306a36Sopenharmony_ci toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), 93662306a36Sopenharmony_ci usb_pipeout(urb->pipe)); 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci /* 3 errors, dummy TD remains inactive */ 93962306a36Sopenharmony_ci status = uhci_maxerr(3); 94062306a36Sopenharmony_ci if (urb->dev->speed == USB_SPEED_LOW) 94162306a36Sopenharmony_ci status |= TD_CTRL_LS; 94262306a36Sopenharmony_ci if (usb_pipein(urb->pipe)) 94362306a36Sopenharmony_ci status |= TD_CTRL_SPD; 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci i = urb->num_mapped_sgs; 94662306a36Sopenharmony_ci if (len > 0 && i > 0) { 94762306a36Sopenharmony_ci sg = urb->sg; 94862306a36Sopenharmony_ci data = sg_dma_address(sg); 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci /* urb->transfer_buffer_length may be smaller than the 95162306a36Sopenharmony_ci * size of the scatterlist (or vice versa) 95262306a36Sopenharmony_ci */ 95362306a36Sopenharmony_ci this_sg_len = min_t(int, sg_dma_len(sg), len); 95462306a36Sopenharmony_ci } else { 95562306a36Sopenharmony_ci sg = NULL; 95662306a36Sopenharmony_ci data = urb->transfer_dma; 95762306a36Sopenharmony_ci this_sg_len = len; 95862306a36Sopenharmony_ci } 95962306a36Sopenharmony_ci /* 96062306a36Sopenharmony_ci * Build the DATA TDs 96162306a36Sopenharmony_ci */ 96262306a36Sopenharmony_ci plink = NULL; 96362306a36Sopenharmony_ci td = qh->dummy_td; 96462306a36Sopenharmony_ci for (;;) { /* Allow zero length packets */ 96562306a36Sopenharmony_ci int pktsze = maxsze; 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci if (len <= pktsze) { /* The last packet */ 96862306a36Sopenharmony_ci pktsze = len; 96962306a36Sopenharmony_ci if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) 97062306a36Sopenharmony_ci status &= ~TD_CTRL_SPD; 97162306a36Sopenharmony_ci } 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci if (plink) { 97462306a36Sopenharmony_ci td = uhci_alloc_td(uhci); 97562306a36Sopenharmony_ci if (!td) 97662306a36Sopenharmony_ci goto nomem; 97762306a36Sopenharmony_ci *plink = LINK_TO_TD(uhci, td); 97862306a36Sopenharmony_ci } 97962306a36Sopenharmony_ci uhci_add_td_to_urbp(td, urbp); 98062306a36Sopenharmony_ci uhci_fill_td(uhci, td, status, 98162306a36Sopenharmony_ci destination | uhci_explen(pktsze) | 98262306a36Sopenharmony_ci (toggle << TD_TOKEN_TOGGLE_SHIFT), 98362306a36Sopenharmony_ci data); 98462306a36Sopenharmony_ci plink = &td->link; 98562306a36Sopenharmony_ci status |= TD_CTRL_ACTIVE; 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci toggle ^= 1; 98862306a36Sopenharmony_ci data += pktsze; 98962306a36Sopenharmony_ci this_sg_len -= pktsze; 99062306a36Sopenharmony_ci len -= maxsze; 99162306a36Sopenharmony_ci if (this_sg_len <= 0) { 99262306a36Sopenharmony_ci if (--i <= 0 || len <= 0) 99362306a36Sopenharmony_ci break; 99462306a36Sopenharmony_ci sg = sg_next(sg); 99562306a36Sopenharmony_ci data = sg_dma_address(sg); 99662306a36Sopenharmony_ci this_sg_len = min_t(int, sg_dma_len(sg), len); 99762306a36Sopenharmony_ci } 99862306a36Sopenharmony_ci } 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci /* 100162306a36Sopenharmony_ci * URB_ZERO_PACKET means adding a 0-length packet, if direction 100262306a36Sopenharmony_ci * is OUT and the transfer_length was an exact multiple of maxsze, 100362306a36Sopenharmony_ci * hence (len = transfer_length - N * maxsze) == 0 100462306a36Sopenharmony_ci * however, if transfer_length == 0, the zero packet was already 100562306a36Sopenharmony_ci * prepared above. 100662306a36Sopenharmony_ci */ 100762306a36Sopenharmony_ci if ((urb->transfer_flags & URB_ZERO_PACKET) && 100862306a36Sopenharmony_ci usb_pipeout(urb->pipe) && len == 0 && 100962306a36Sopenharmony_ci urb->transfer_buffer_length > 0) { 101062306a36Sopenharmony_ci td = uhci_alloc_td(uhci); 101162306a36Sopenharmony_ci if (!td) 101262306a36Sopenharmony_ci goto nomem; 101362306a36Sopenharmony_ci *plink = LINK_TO_TD(uhci, td); 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci uhci_add_td_to_urbp(td, urbp); 101662306a36Sopenharmony_ci uhci_fill_td(uhci, td, status, 101762306a36Sopenharmony_ci destination | uhci_explen(0) | 101862306a36Sopenharmony_ci (toggle << TD_TOKEN_TOGGLE_SHIFT), 101962306a36Sopenharmony_ci data); 102062306a36Sopenharmony_ci plink = &td->link; 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci toggle ^= 1; 102362306a36Sopenharmony_ci } 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci /* Set the interrupt-on-completion flag on the last packet. 102662306a36Sopenharmony_ci * A more-or-less typical 4 KB URB (= size of one memory page) 102762306a36Sopenharmony_ci * will require about 3 ms to transfer; that's a little on the 102862306a36Sopenharmony_ci * fast side but not enough to justify delaying an interrupt 102962306a36Sopenharmony_ci * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT 103062306a36Sopenharmony_ci * flag setting. */ 103162306a36Sopenharmony_ci td->status |= cpu_to_hc32(uhci, TD_CTRL_IOC); 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci /* 103462306a36Sopenharmony_ci * Build the new dummy TD and activate the old one 103562306a36Sopenharmony_ci */ 103662306a36Sopenharmony_ci td = uhci_alloc_td(uhci); 103762306a36Sopenharmony_ci if (!td) 103862306a36Sopenharmony_ci goto nomem; 103962306a36Sopenharmony_ci *plink = LINK_TO_TD(uhci, td); 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci uhci_fill_td(uhci, td, 0, USB_PID_OUT | uhci_explen(0), 0); 104262306a36Sopenharmony_ci wmb(); 104362306a36Sopenharmony_ci qh->dummy_td->status |= cpu_to_hc32(uhci, TD_CTRL_ACTIVE); 104462306a36Sopenharmony_ci qh->dummy_td = td; 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), 104762306a36Sopenharmony_ci usb_pipeout(urb->pipe), toggle); 104862306a36Sopenharmony_ci return 0; 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_cinomem: 105162306a36Sopenharmony_ci /* Remove the dummy TD from the td_list so it doesn't get freed */ 105262306a36Sopenharmony_ci uhci_remove_td_from_urbp(qh->dummy_td); 105362306a36Sopenharmony_ci return -ENOMEM; 105462306a36Sopenharmony_ci} 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_cistatic int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, 105762306a36Sopenharmony_ci struct uhci_qh *qh) 105862306a36Sopenharmony_ci{ 105962306a36Sopenharmony_ci int ret; 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci /* Can't have low-speed bulk transfers */ 106262306a36Sopenharmony_ci if (urb->dev->speed == USB_SPEED_LOW) 106362306a36Sopenharmony_ci return -EINVAL; 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci if (qh->state != QH_STATE_ACTIVE) 106662306a36Sopenharmony_ci qh->skel = SKEL_BULK; 106762306a36Sopenharmony_ci ret = uhci_submit_common(uhci, urb, qh); 106862306a36Sopenharmony_ci if (ret == 0) 106962306a36Sopenharmony_ci uhci_add_fsbr(uhci, urb); 107062306a36Sopenharmony_ci return ret; 107162306a36Sopenharmony_ci} 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_cistatic int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, 107462306a36Sopenharmony_ci struct uhci_qh *qh) 107562306a36Sopenharmony_ci{ 107662306a36Sopenharmony_ci int ret; 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci /* USB 1.1 interrupt transfers only involve one packet per interval. 107962306a36Sopenharmony_ci * Drivers can submit URBs of any length, but longer ones will need 108062306a36Sopenharmony_ci * multiple intervals to complete. 108162306a36Sopenharmony_ci */ 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci if (!qh->bandwidth_reserved) { 108462306a36Sopenharmony_ci int exponent; 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci /* Figure out which power-of-two queue to use */ 108762306a36Sopenharmony_ci for (exponent = 7; exponent >= 0; --exponent) { 108862306a36Sopenharmony_ci if ((1 << exponent) <= urb->interval) 108962306a36Sopenharmony_ci break; 109062306a36Sopenharmony_ci } 109162306a36Sopenharmony_ci if (exponent < 0) 109262306a36Sopenharmony_ci return -EINVAL; 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci /* If the slot is full, try a lower period */ 109562306a36Sopenharmony_ci do { 109662306a36Sopenharmony_ci qh->period = 1 << exponent; 109762306a36Sopenharmony_ci qh->skel = SKEL_INDEX(exponent); 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_ci /* For now, interrupt phase is fixed by the layout 110062306a36Sopenharmony_ci * of the QH lists. 110162306a36Sopenharmony_ci */ 110262306a36Sopenharmony_ci qh->phase = (qh->period / 2) & (MAX_PHASE - 1); 110362306a36Sopenharmony_ci ret = uhci_check_bandwidth(uhci, qh); 110462306a36Sopenharmony_ci } while (ret != 0 && --exponent >= 0); 110562306a36Sopenharmony_ci if (ret) 110662306a36Sopenharmony_ci return ret; 110762306a36Sopenharmony_ci } else if (qh->period > urb->interval) 110862306a36Sopenharmony_ci return -EINVAL; /* Can't decrease the period */ 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci ret = uhci_submit_common(uhci, urb, qh); 111162306a36Sopenharmony_ci if (ret == 0) { 111262306a36Sopenharmony_ci urb->interval = qh->period; 111362306a36Sopenharmony_ci if (!qh->bandwidth_reserved) 111462306a36Sopenharmony_ci uhci_reserve_bandwidth(uhci, qh); 111562306a36Sopenharmony_ci } 111662306a36Sopenharmony_ci return ret; 111762306a36Sopenharmony_ci} 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci/* 112062306a36Sopenharmony_ci * Fix up the data structures following a short transfer 112162306a36Sopenharmony_ci */ 112262306a36Sopenharmony_cistatic int uhci_fixup_short_transfer(struct uhci_hcd *uhci, 112362306a36Sopenharmony_ci struct uhci_qh *qh, struct urb_priv *urbp) 112462306a36Sopenharmony_ci{ 112562306a36Sopenharmony_ci struct uhci_td *td; 112662306a36Sopenharmony_ci struct list_head *tmp; 112762306a36Sopenharmony_ci int ret; 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci td = list_entry(urbp->td_list.prev, struct uhci_td, list); 113062306a36Sopenharmony_ci if (qh->type == USB_ENDPOINT_XFER_CONTROL) { 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_ci /* When a control transfer is short, we have to restart 113362306a36Sopenharmony_ci * the queue at the status stage transaction, which is 113462306a36Sopenharmony_ci * the last TD. */ 113562306a36Sopenharmony_ci WARN_ON(list_empty(&urbp->td_list)); 113662306a36Sopenharmony_ci qh->element = LINK_TO_TD(uhci, td); 113762306a36Sopenharmony_ci tmp = td->list.prev; 113862306a36Sopenharmony_ci ret = -EINPROGRESS; 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci } else { 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_ci /* When a bulk/interrupt transfer is short, we have to 114362306a36Sopenharmony_ci * fix up the toggles of the following URBs on the queue 114462306a36Sopenharmony_ci * before restarting the queue at the next URB. */ 114562306a36Sopenharmony_ci qh->initial_toggle = 114662306a36Sopenharmony_ci uhci_toggle(td_token(uhci, qh->post_td)) ^ 1; 114762306a36Sopenharmony_ci uhci_fixup_toggles(uhci, qh, 1); 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci if (list_empty(&urbp->td_list)) 115062306a36Sopenharmony_ci td = qh->post_td; 115162306a36Sopenharmony_ci qh->element = td->link; 115262306a36Sopenharmony_ci tmp = urbp->td_list.prev; 115362306a36Sopenharmony_ci ret = 0; 115462306a36Sopenharmony_ci } 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci /* Remove all the TDs we skipped over, from tmp back to the start */ 115762306a36Sopenharmony_ci while (tmp != &urbp->td_list) { 115862306a36Sopenharmony_ci td = list_entry(tmp, struct uhci_td, list); 115962306a36Sopenharmony_ci tmp = tmp->prev; 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_ci uhci_remove_td_from_urbp(td); 116262306a36Sopenharmony_ci uhci_free_td(uhci, td); 116362306a36Sopenharmony_ci } 116462306a36Sopenharmony_ci return ret; 116562306a36Sopenharmony_ci} 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_ci/* 116862306a36Sopenharmony_ci * Common result for control, bulk, and interrupt 116962306a36Sopenharmony_ci */ 117062306a36Sopenharmony_cistatic int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) 117162306a36Sopenharmony_ci{ 117262306a36Sopenharmony_ci struct urb_priv *urbp = urb->hcpriv; 117362306a36Sopenharmony_ci struct uhci_qh *qh = urbp->qh; 117462306a36Sopenharmony_ci struct uhci_td *td, *tmp; 117562306a36Sopenharmony_ci unsigned status; 117662306a36Sopenharmony_ci int ret = 0; 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { 117962306a36Sopenharmony_ci unsigned int ctrlstat; 118062306a36Sopenharmony_ci int len; 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci ctrlstat = td_status(uhci, td); 118362306a36Sopenharmony_ci status = uhci_status_bits(ctrlstat); 118462306a36Sopenharmony_ci if (status & TD_CTRL_ACTIVE) 118562306a36Sopenharmony_ci return -EINPROGRESS; 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci len = uhci_actual_length(ctrlstat); 118862306a36Sopenharmony_ci urb->actual_length += len; 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci if (status) { 119162306a36Sopenharmony_ci ret = uhci_map_status(status, 119262306a36Sopenharmony_ci uhci_packetout(td_token(uhci, td))); 119362306a36Sopenharmony_ci if ((debug == 1 && ret != -EPIPE) || debug > 1) { 119462306a36Sopenharmony_ci /* Some debugging code */ 119562306a36Sopenharmony_ci dev_dbg(&urb->dev->dev, 119662306a36Sopenharmony_ci "%s: failed with status %x\n", 119762306a36Sopenharmony_ci __func__, status); 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_ci if (debug > 1 && errbuf) { 120062306a36Sopenharmony_ci /* Print the chain for debugging */ 120162306a36Sopenharmony_ci uhci_show_qh(uhci, urbp->qh, errbuf, 120262306a36Sopenharmony_ci ERRBUF_LEN - EXTRA_SPACE, 0); 120362306a36Sopenharmony_ci lprintk(errbuf); 120462306a36Sopenharmony_ci } 120562306a36Sopenharmony_ci } 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci /* Did we receive a short packet? */ 120862306a36Sopenharmony_ci } else if (len < uhci_expected_length(td_token(uhci, td))) { 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci /* For control transfers, go to the status TD if 121162306a36Sopenharmony_ci * this isn't already the last data TD */ 121262306a36Sopenharmony_ci if (qh->type == USB_ENDPOINT_XFER_CONTROL) { 121362306a36Sopenharmony_ci if (td->list.next != urbp->td_list.prev) 121462306a36Sopenharmony_ci ret = 1; 121562306a36Sopenharmony_ci } 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_ci /* For bulk and interrupt, this may be an error */ 121862306a36Sopenharmony_ci else if (urb->transfer_flags & URB_SHORT_NOT_OK) 121962306a36Sopenharmony_ci ret = -EREMOTEIO; 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci /* Fixup needed only if this isn't the URB's last TD */ 122262306a36Sopenharmony_ci else if (&td->list != urbp->td_list.prev) 122362306a36Sopenharmony_ci ret = 1; 122462306a36Sopenharmony_ci } 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci uhci_remove_td_from_urbp(td); 122762306a36Sopenharmony_ci if (qh->post_td) 122862306a36Sopenharmony_ci uhci_free_td(uhci, qh->post_td); 122962306a36Sopenharmony_ci qh->post_td = td; 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci if (ret != 0) 123262306a36Sopenharmony_ci goto err; 123362306a36Sopenharmony_ci } 123462306a36Sopenharmony_ci return ret; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_cierr: 123762306a36Sopenharmony_ci if (ret < 0) { 123862306a36Sopenharmony_ci /* Note that the queue has stopped and save 123962306a36Sopenharmony_ci * the next toggle value */ 124062306a36Sopenharmony_ci qh->element = UHCI_PTR_TERM(uhci); 124162306a36Sopenharmony_ci qh->is_stopped = 1; 124262306a36Sopenharmony_ci qh->needs_fixup = (qh->type != USB_ENDPOINT_XFER_CONTROL); 124362306a36Sopenharmony_ci qh->initial_toggle = uhci_toggle(td_token(uhci, td)) ^ 124462306a36Sopenharmony_ci (ret == -EREMOTEIO); 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci } else /* Short packet received */ 124762306a36Sopenharmony_ci ret = uhci_fixup_short_transfer(uhci, qh, urbp); 124862306a36Sopenharmony_ci return ret; 124962306a36Sopenharmony_ci} 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci/* 125262306a36Sopenharmony_ci * Isochronous transfers 125362306a36Sopenharmony_ci */ 125462306a36Sopenharmony_cistatic int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, 125562306a36Sopenharmony_ci struct uhci_qh *qh) 125662306a36Sopenharmony_ci{ 125762306a36Sopenharmony_ci struct uhci_td *td = NULL; /* Since urb->number_of_packets > 0 */ 125862306a36Sopenharmony_ci int i; 125962306a36Sopenharmony_ci unsigned frame, next; 126062306a36Sopenharmony_ci unsigned long destination, status; 126162306a36Sopenharmony_ci struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; 126262306a36Sopenharmony_ci 126362306a36Sopenharmony_ci /* Values must not be too big (could overflow below) */ 126462306a36Sopenharmony_ci if (urb->interval >= UHCI_NUMFRAMES || 126562306a36Sopenharmony_ci urb->number_of_packets >= UHCI_NUMFRAMES) 126662306a36Sopenharmony_ci return -EFBIG; 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci uhci_get_current_frame_number(uhci); 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci /* Check the period and figure out the starting frame number */ 127162306a36Sopenharmony_ci if (!qh->bandwidth_reserved) { 127262306a36Sopenharmony_ci qh->period = urb->interval; 127362306a36Sopenharmony_ci qh->phase = -1; /* Find the best phase */ 127462306a36Sopenharmony_ci i = uhci_check_bandwidth(uhci, qh); 127562306a36Sopenharmony_ci if (i) 127662306a36Sopenharmony_ci return i; 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_ci /* Allow a little time to allocate the TDs */ 127962306a36Sopenharmony_ci next = uhci->frame_number + 10; 128062306a36Sopenharmony_ci frame = qh->phase; 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci /* Round up to the first available slot */ 128362306a36Sopenharmony_ci frame += (next - frame + qh->period - 1) & -qh->period; 128462306a36Sopenharmony_ci 128562306a36Sopenharmony_ci } else if (qh->period != urb->interval) { 128662306a36Sopenharmony_ci return -EINVAL; /* Can't change the period */ 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci } else { 128962306a36Sopenharmony_ci next = uhci->frame_number + 1; 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci /* Find the next unused frame */ 129262306a36Sopenharmony_ci if (list_empty(&qh->queue)) { 129362306a36Sopenharmony_ci frame = qh->iso_frame; 129462306a36Sopenharmony_ci } else { 129562306a36Sopenharmony_ci struct urb *lurb; 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci lurb = list_entry(qh->queue.prev, 129862306a36Sopenharmony_ci struct urb_priv, node)->urb; 129962306a36Sopenharmony_ci frame = lurb->start_frame + 130062306a36Sopenharmony_ci lurb->number_of_packets * 130162306a36Sopenharmony_ci lurb->interval; 130262306a36Sopenharmony_ci } 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci /* Fell behind? */ 130562306a36Sopenharmony_ci if (!uhci_frame_before_eq(next, frame)) { 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci /* USB_ISO_ASAP: Round up to the first available slot */ 130862306a36Sopenharmony_ci if (urb->transfer_flags & URB_ISO_ASAP) 130962306a36Sopenharmony_ci frame += (next - frame + qh->period - 1) & 131062306a36Sopenharmony_ci -qh->period; 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci /* 131362306a36Sopenharmony_ci * Not ASAP: Use the next slot in the stream, 131462306a36Sopenharmony_ci * no matter what. 131562306a36Sopenharmony_ci */ 131662306a36Sopenharmony_ci else if (!uhci_frame_before_eq(next, 131762306a36Sopenharmony_ci frame + (urb->number_of_packets - 1) * 131862306a36Sopenharmony_ci qh->period)) 131962306a36Sopenharmony_ci dev_dbg(uhci_dev(uhci), "iso underrun %p (%u+%u < %u)\n", 132062306a36Sopenharmony_ci urb, frame, 132162306a36Sopenharmony_ci (urb->number_of_packets - 1) * 132262306a36Sopenharmony_ci qh->period, 132362306a36Sopenharmony_ci next); 132462306a36Sopenharmony_ci } 132562306a36Sopenharmony_ci } 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_ci /* Make sure we won't have to go too far into the future */ 132862306a36Sopenharmony_ci if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES, 132962306a36Sopenharmony_ci frame + urb->number_of_packets * urb->interval)) 133062306a36Sopenharmony_ci return -EFBIG; 133162306a36Sopenharmony_ci urb->start_frame = frame; 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci status = TD_CTRL_ACTIVE | TD_CTRL_IOS; 133462306a36Sopenharmony_ci destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci for (i = 0; i < urb->number_of_packets; i++) { 133762306a36Sopenharmony_ci td = uhci_alloc_td(uhci); 133862306a36Sopenharmony_ci if (!td) 133962306a36Sopenharmony_ci return -ENOMEM; 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci uhci_add_td_to_urbp(td, urbp); 134262306a36Sopenharmony_ci uhci_fill_td(uhci, td, status, destination | 134362306a36Sopenharmony_ci uhci_explen(urb->iso_frame_desc[i].length), 134462306a36Sopenharmony_ci urb->transfer_dma + 134562306a36Sopenharmony_ci urb->iso_frame_desc[i].offset); 134662306a36Sopenharmony_ci } 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci /* Set the interrupt-on-completion flag on the last packet. */ 134962306a36Sopenharmony_ci td->status |= cpu_to_hc32(uhci, TD_CTRL_IOC); 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci /* Add the TDs to the frame list */ 135262306a36Sopenharmony_ci frame = urb->start_frame; 135362306a36Sopenharmony_ci list_for_each_entry(td, &urbp->td_list, list) { 135462306a36Sopenharmony_ci uhci_insert_td_in_frame_list(uhci, td, frame); 135562306a36Sopenharmony_ci frame += qh->period; 135662306a36Sopenharmony_ci } 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci if (list_empty(&qh->queue)) { 135962306a36Sopenharmony_ci qh->iso_packet_desc = &urb->iso_frame_desc[0]; 136062306a36Sopenharmony_ci qh->iso_frame = urb->start_frame; 136162306a36Sopenharmony_ci } 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci qh->skel = SKEL_ISO; 136462306a36Sopenharmony_ci if (!qh->bandwidth_reserved) 136562306a36Sopenharmony_ci uhci_reserve_bandwidth(uhci, qh); 136662306a36Sopenharmony_ci return 0; 136762306a36Sopenharmony_ci} 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_cistatic int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) 137062306a36Sopenharmony_ci{ 137162306a36Sopenharmony_ci struct uhci_td *td, *tmp; 137262306a36Sopenharmony_ci struct urb_priv *urbp = urb->hcpriv; 137362306a36Sopenharmony_ci struct uhci_qh *qh = urbp->qh; 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci list_for_each_entry_safe(td, tmp, &urbp->td_list, list) { 137662306a36Sopenharmony_ci unsigned int ctrlstat; 137762306a36Sopenharmony_ci int status; 137862306a36Sopenharmony_ci int actlength; 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci if (uhci_frame_before_eq(uhci->cur_iso_frame, qh->iso_frame)) 138162306a36Sopenharmony_ci return -EINPROGRESS; 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci uhci_remove_tds_from_frame(uhci, qh->iso_frame); 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_ci ctrlstat = td_status(uhci, td); 138662306a36Sopenharmony_ci if (ctrlstat & TD_CTRL_ACTIVE) { 138762306a36Sopenharmony_ci status = -EXDEV; /* TD was added too late? */ 138862306a36Sopenharmony_ci } else { 138962306a36Sopenharmony_ci status = uhci_map_status(uhci_status_bits(ctrlstat), 139062306a36Sopenharmony_ci usb_pipeout(urb->pipe)); 139162306a36Sopenharmony_ci actlength = uhci_actual_length(ctrlstat); 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci urb->actual_length += actlength; 139462306a36Sopenharmony_ci qh->iso_packet_desc->actual_length = actlength; 139562306a36Sopenharmony_ci qh->iso_packet_desc->status = status; 139662306a36Sopenharmony_ci } 139762306a36Sopenharmony_ci if (status) 139862306a36Sopenharmony_ci urb->error_count++; 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ci uhci_remove_td_from_urbp(td); 140162306a36Sopenharmony_ci uhci_free_td(uhci, td); 140262306a36Sopenharmony_ci qh->iso_frame += qh->period; 140362306a36Sopenharmony_ci ++qh->iso_packet_desc; 140462306a36Sopenharmony_ci } 140562306a36Sopenharmony_ci return 0; 140662306a36Sopenharmony_ci} 140762306a36Sopenharmony_ci 140862306a36Sopenharmony_cistatic int uhci_urb_enqueue(struct usb_hcd *hcd, 140962306a36Sopenharmony_ci struct urb *urb, gfp_t mem_flags) 141062306a36Sopenharmony_ci{ 141162306a36Sopenharmony_ci int ret; 141262306a36Sopenharmony_ci struct uhci_hcd *uhci = hcd_to_uhci(hcd); 141362306a36Sopenharmony_ci unsigned long flags; 141462306a36Sopenharmony_ci struct urb_priv *urbp; 141562306a36Sopenharmony_ci struct uhci_qh *qh; 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci spin_lock_irqsave(&uhci->lock, flags); 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci ret = usb_hcd_link_urb_to_ep(hcd, urb); 142062306a36Sopenharmony_ci if (ret) 142162306a36Sopenharmony_ci goto done_not_linked; 142262306a36Sopenharmony_ci 142362306a36Sopenharmony_ci ret = -ENOMEM; 142462306a36Sopenharmony_ci urbp = uhci_alloc_urb_priv(uhci, urb); 142562306a36Sopenharmony_ci if (!urbp) 142662306a36Sopenharmony_ci goto done; 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci if (urb->ep->hcpriv) 142962306a36Sopenharmony_ci qh = urb->ep->hcpriv; 143062306a36Sopenharmony_ci else { 143162306a36Sopenharmony_ci qh = uhci_alloc_qh(uhci, urb->dev, urb->ep); 143262306a36Sopenharmony_ci if (!qh) 143362306a36Sopenharmony_ci goto err_no_qh; 143462306a36Sopenharmony_ci } 143562306a36Sopenharmony_ci urbp->qh = qh; 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci switch (qh->type) { 143862306a36Sopenharmony_ci case USB_ENDPOINT_XFER_CONTROL: 143962306a36Sopenharmony_ci ret = uhci_submit_control(uhci, urb, qh); 144062306a36Sopenharmony_ci break; 144162306a36Sopenharmony_ci case USB_ENDPOINT_XFER_BULK: 144262306a36Sopenharmony_ci ret = uhci_submit_bulk(uhci, urb, qh); 144362306a36Sopenharmony_ci break; 144462306a36Sopenharmony_ci case USB_ENDPOINT_XFER_INT: 144562306a36Sopenharmony_ci ret = uhci_submit_interrupt(uhci, urb, qh); 144662306a36Sopenharmony_ci break; 144762306a36Sopenharmony_ci case USB_ENDPOINT_XFER_ISOC: 144862306a36Sopenharmony_ci urb->error_count = 0; 144962306a36Sopenharmony_ci ret = uhci_submit_isochronous(uhci, urb, qh); 145062306a36Sopenharmony_ci break; 145162306a36Sopenharmony_ci } 145262306a36Sopenharmony_ci if (ret != 0) 145362306a36Sopenharmony_ci goto err_submit_failed; 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci /* Add this URB to the QH */ 145662306a36Sopenharmony_ci list_add_tail(&urbp->node, &qh->queue); 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_ci /* If the new URB is the first and only one on this QH then either 145962306a36Sopenharmony_ci * the QH is new and idle or else it's unlinked and waiting to 146062306a36Sopenharmony_ci * become idle, so we can activate it right away. But only if the 146162306a36Sopenharmony_ci * queue isn't stopped. */ 146262306a36Sopenharmony_ci if (qh->queue.next == &urbp->node && !qh->is_stopped) { 146362306a36Sopenharmony_ci uhci_activate_qh(uhci, qh); 146462306a36Sopenharmony_ci uhci_urbp_wants_fsbr(uhci, urbp); 146562306a36Sopenharmony_ci } 146662306a36Sopenharmony_ci goto done; 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_cierr_submit_failed: 146962306a36Sopenharmony_ci if (qh->state == QH_STATE_IDLE) 147062306a36Sopenharmony_ci uhci_make_qh_idle(uhci, qh); /* Reclaim unused QH */ 147162306a36Sopenharmony_cierr_no_qh: 147262306a36Sopenharmony_ci uhci_free_urb_priv(uhci, urbp); 147362306a36Sopenharmony_cidone: 147462306a36Sopenharmony_ci if (ret) 147562306a36Sopenharmony_ci usb_hcd_unlink_urb_from_ep(hcd, urb); 147662306a36Sopenharmony_cidone_not_linked: 147762306a36Sopenharmony_ci spin_unlock_irqrestore(&uhci->lock, flags); 147862306a36Sopenharmony_ci return ret; 147962306a36Sopenharmony_ci} 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_cistatic int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) 148262306a36Sopenharmony_ci{ 148362306a36Sopenharmony_ci struct uhci_hcd *uhci = hcd_to_uhci(hcd); 148462306a36Sopenharmony_ci unsigned long flags; 148562306a36Sopenharmony_ci struct uhci_qh *qh; 148662306a36Sopenharmony_ci int rc; 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci spin_lock_irqsave(&uhci->lock, flags); 148962306a36Sopenharmony_ci rc = usb_hcd_check_unlink_urb(hcd, urb, status); 149062306a36Sopenharmony_ci if (rc) 149162306a36Sopenharmony_ci goto done; 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci qh = ((struct urb_priv *) urb->hcpriv)->qh; 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci /* Remove Isochronous TDs from the frame list ASAP */ 149662306a36Sopenharmony_ci if (qh->type == USB_ENDPOINT_XFER_ISOC) { 149762306a36Sopenharmony_ci uhci_unlink_isochronous_tds(uhci, urb); 149862306a36Sopenharmony_ci mb(); 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci /* If the URB has already started, update the QH unlink time */ 150162306a36Sopenharmony_ci uhci_get_current_frame_number(uhci); 150262306a36Sopenharmony_ci if (uhci_frame_before_eq(urb->start_frame, uhci->frame_number)) 150362306a36Sopenharmony_ci qh->unlink_frame = uhci->frame_number; 150462306a36Sopenharmony_ci } 150562306a36Sopenharmony_ci 150662306a36Sopenharmony_ci uhci_unlink_qh(uhci, qh); 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_cidone: 150962306a36Sopenharmony_ci spin_unlock_irqrestore(&uhci->lock, flags); 151062306a36Sopenharmony_ci return rc; 151162306a36Sopenharmony_ci} 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci/* 151462306a36Sopenharmony_ci * Finish unlinking an URB and give it back 151562306a36Sopenharmony_ci */ 151662306a36Sopenharmony_cistatic void uhci_giveback_urb(struct uhci_hcd *uhci, struct uhci_qh *qh, 151762306a36Sopenharmony_ci struct urb *urb, int status) 151862306a36Sopenharmony_ci__releases(uhci->lock) 151962306a36Sopenharmony_ci__acquires(uhci->lock) 152062306a36Sopenharmony_ci{ 152162306a36Sopenharmony_ci struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_ci if (qh->type == USB_ENDPOINT_XFER_CONTROL) { 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci /* Subtract off the length of the SETUP packet from 152662306a36Sopenharmony_ci * urb->actual_length. 152762306a36Sopenharmony_ci */ 152862306a36Sopenharmony_ci urb->actual_length -= min_t(u32, 8, urb->actual_length); 152962306a36Sopenharmony_ci } 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_ci /* When giving back the first URB in an Isochronous queue, 153262306a36Sopenharmony_ci * reinitialize the QH's iso-related members for the next URB. */ 153362306a36Sopenharmony_ci else if (qh->type == USB_ENDPOINT_XFER_ISOC && 153462306a36Sopenharmony_ci urbp->node.prev == &qh->queue && 153562306a36Sopenharmony_ci urbp->node.next != &qh->queue) { 153662306a36Sopenharmony_ci struct urb *nurb = list_entry(urbp->node.next, 153762306a36Sopenharmony_ci struct urb_priv, node)->urb; 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_ci qh->iso_packet_desc = &nurb->iso_frame_desc[0]; 154062306a36Sopenharmony_ci qh->iso_frame = nurb->start_frame; 154162306a36Sopenharmony_ci } 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci /* Take the URB off the QH's queue. If the queue is now empty, 154462306a36Sopenharmony_ci * this is a perfect time for a toggle fixup. */ 154562306a36Sopenharmony_ci list_del_init(&urbp->node); 154662306a36Sopenharmony_ci if (list_empty(&qh->queue) && qh->needs_fixup) { 154762306a36Sopenharmony_ci usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), 154862306a36Sopenharmony_ci usb_pipeout(urb->pipe), qh->initial_toggle); 154962306a36Sopenharmony_ci qh->needs_fixup = 0; 155062306a36Sopenharmony_ci } 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci uhci_free_urb_priv(uhci, urbp); 155362306a36Sopenharmony_ci usb_hcd_unlink_urb_from_ep(uhci_to_hcd(uhci), urb); 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci spin_unlock(&uhci->lock); 155662306a36Sopenharmony_ci usb_hcd_giveback_urb(uhci_to_hcd(uhci), urb, status); 155762306a36Sopenharmony_ci spin_lock(&uhci->lock); 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci /* If the queue is now empty, we can unlink the QH and give up its 156062306a36Sopenharmony_ci * reserved bandwidth. */ 156162306a36Sopenharmony_ci if (list_empty(&qh->queue)) { 156262306a36Sopenharmony_ci uhci_unlink_qh(uhci, qh); 156362306a36Sopenharmony_ci if (qh->bandwidth_reserved) 156462306a36Sopenharmony_ci uhci_release_bandwidth(uhci, qh); 156562306a36Sopenharmony_ci } 156662306a36Sopenharmony_ci} 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_ci/* 156962306a36Sopenharmony_ci * Scan the URBs in a QH's queue 157062306a36Sopenharmony_ci */ 157162306a36Sopenharmony_ci#define QH_FINISHED_UNLINKING(qh) \ 157262306a36Sopenharmony_ci (qh->state == QH_STATE_UNLINKING && \ 157362306a36Sopenharmony_ci uhci->frame_number + uhci->is_stopped != qh->unlink_frame) 157462306a36Sopenharmony_ci 157562306a36Sopenharmony_cistatic void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) 157662306a36Sopenharmony_ci{ 157762306a36Sopenharmony_ci struct urb_priv *urbp; 157862306a36Sopenharmony_ci struct urb *urb; 157962306a36Sopenharmony_ci int status; 158062306a36Sopenharmony_ci 158162306a36Sopenharmony_ci while (!list_empty(&qh->queue)) { 158262306a36Sopenharmony_ci urbp = list_entry(qh->queue.next, struct urb_priv, node); 158362306a36Sopenharmony_ci urb = urbp->urb; 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_ci if (qh->type == USB_ENDPOINT_XFER_ISOC) 158662306a36Sopenharmony_ci status = uhci_result_isochronous(uhci, urb); 158762306a36Sopenharmony_ci else 158862306a36Sopenharmony_ci status = uhci_result_common(uhci, urb); 158962306a36Sopenharmony_ci if (status == -EINPROGRESS) 159062306a36Sopenharmony_ci break; 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci /* Dequeued but completed URBs can't be given back unless 159362306a36Sopenharmony_ci * the QH is stopped or has finished unlinking. */ 159462306a36Sopenharmony_ci if (urb->unlinked) { 159562306a36Sopenharmony_ci if (QH_FINISHED_UNLINKING(qh)) 159662306a36Sopenharmony_ci qh->is_stopped = 1; 159762306a36Sopenharmony_ci else if (!qh->is_stopped) 159862306a36Sopenharmony_ci return; 159962306a36Sopenharmony_ci } 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_ci uhci_giveback_urb(uhci, qh, urb, status); 160262306a36Sopenharmony_ci if (status < 0) 160362306a36Sopenharmony_ci break; 160462306a36Sopenharmony_ci } 160562306a36Sopenharmony_ci 160662306a36Sopenharmony_ci /* If the QH is neither stopped nor finished unlinking (normal case), 160762306a36Sopenharmony_ci * our work here is done. */ 160862306a36Sopenharmony_ci if (QH_FINISHED_UNLINKING(qh)) 160962306a36Sopenharmony_ci qh->is_stopped = 1; 161062306a36Sopenharmony_ci else if (!qh->is_stopped) 161162306a36Sopenharmony_ci return; 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_ci /* Otherwise give back each of the dequeued URBs */ 161462306a36Sopenharmony_cirestart: 161562306a36Sopenharmony_ci list_for_each_entry(urbp, &qh->queue, node) { 161662306a36Sopenharmony_ci urb = urbp->urb; 161762306a36Sopenharmony_ci if (urb->unlinked) { 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci /* Fix up the TD links and save the toggles for 162062306a36Sopenharmony_ci * non-Isochronous queues. For Isochronous queues, 162162306a36Sopenharmony_ci * test for too-recent dequeues. */ 162262306a36Sopenharmony_ci if (!uhci_cleanup_queue(uhci, qh, urb)) { 162362306a36Sopenharmony_ci qh->is_stopped = 0; 162462306a36Sopenharmony_ci return; 162562306a36Sopenharmony_ci } 162662306a36Sopenharmony_ci uhci_giveback_urb(uhci, qh, urb, 0); 162762306a36Sopenharmony_ci goto restart; 162862306a36Sopenharmony_ci } 162962306a36Sopenharmony_ci } 163062306a36Sopenharmony_ci qh->is_stopped = 0; 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci /* There are no more dequeued URBs. If there are still URBs on the 163362306a36Sopenharmony_ci * queue, the QH can now be re-activated. */ 163462306a36Sopenharmony_ci if (!list_empty(&qh->queue)) { 163562306a36Sopenharmony_ci if (qh->needs_fixup) 163662306a36Sopenharmony_ci uhci_fixup_toggles(uhci, qh, 0); 163762306a36Sopenharmony_ci 163862306a36Sopenharmony_ci /* If the first URB on the queue wants FSBR but its time 163962306a36Sopenharmony_ci * limit has expired, set the next TD to interrupt on 164062306a36Sopenharmony_ci * completion before reactivating the QH. */ 164162306a36Sopenharmony_ci urbp = list_entry(qh->queue.next, struct urb_priv, node); 164262306a36Sopenharmony_ci if (urbp->fsbr && qh->wait_expired) { 164362306a36Sopenharmony_ci struct uhci_td *td = list_entry(urbp->td_list.next, 164462306a36Sopenharmony_ci struct uhci_td, list); 164562306a36Sopenharmony_ci 164662306a36Sopenharmony_ci td->status |= cpu_to_hc32(uhci, TD_CTRL_IOC); 164762306a36Sopenharmony_ci } 164862306a36Sopenharmony_ci 164962306a36Sopenharmony_ci uhci_activate_qh(uhci, qh); 165062306a36Sopenharmony_ci } 165162306a36Sopenharmony_ci 165262306a36Sopenharmony_ci /* The queue is empty. The QH can become idle if it is fully 165362306a36Sopenharmony_ci * unlinked. */ 165462306a36Sopenharmony_ci else if (QH_FINISHED_UNLINKING(qh)) 165562306a36Sopenharmony_ci uhci_make_qh_idle(uhci, qh); 165662306a36Sopenharmony_ci} 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci/* 165962306a36Sopenharmony_ci * Check for queues that have made some forward progress. 166062306a36Sopenharmony_ci * Returns 0 if the queue is not Isochronous, is ACTIVE, and 166162306a36Sopenharmony_ci * has not advanced since last examined; 1 otherwise. 166262306a36Sopenharmony_ci * 166362306a36Sopenharmony_ci * Early Intel controllers have a bug which causes qh->element sometimes 166462306a36Sopenharmony_ci * not to advance when a TD completes successfully. The queue remains 166562306a36Sopenharmony_ci * stuck on the inactive completed TD. We detect such cases and advance 166662306a36Sopenharmony_ci * the element pointer by hand. 166762306a36Sopenharmony_ci */ 166862306a36Sopenharmony_cistatic int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) 166962306a36Sopenharmony_ci{ 167062306a36Sopenharmony_ci struct urb_priv *urbp = NULL; 167162306a36Sopenharmony_ci struct uhci_td *td; 167262306a36Sopenharmony_ci int ret = 1; 167362306a36Sopenharmony_ci unsigned status; 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_ci if (qh->type == USB_ENDPOINT_XFER_ISOC) 167662306a36Sopenharmony_ci goto done; 167762306a36Sopenharmony_ci 167862306a36Sopenharmony_ci /* Treat an UNLINKING queue as though it hasn't advanced. 167962306a36Sopenharmony_ci * This is okay because reactivation will treat it as though 168062306a36Sopenharmony_ci * it has advanced, and if it is going to become IDLE then 168162306a36Sopenharmony_ci * this doesn't matter anyway. Furthermore it's possible 168262306a36Sopenharmony_ci * for an UNLINKING queue not to have any URBs at all, or 168362306a36Sopenharmony_ci * for its first URB not to have any TDs (if it was dequeued 168462306a36Sopenharmony_ci * just as it completed). So it's not easy in any case to 168562306a36Sopenharmony_ci * test whether such queues have advanced. */ 168662306a36Sopenharmony_ci if (qh->state != QH_STATE_ACTIVE) { 168762306a36Sopenharmony_ci urbp = NULL; 168862306a36Sopenharmony_ci status = 0; 168962306a36Sopenharmony_ci 169062306a36Sopenharmony_ci } else { 169162306a36Sopenharmony_ci urbp = list_entry(qh->queue.next, struct urb_priv, node); 169262306a36Sopenharmony_ci td = list_entry(urbp->td_list.next, struct uhci_td, list); 169362306a36Sopenharmony_ci status = td_status(uhci, td); 169462306a36Sopenharmony_ci if (!(status & TD_CTRL_ACTIVE)) { 169562306a36Sopenharmony_ci 169662306a36Sopenharmony_ci /* We're okay, the queue has advanced */ 169762306a36Sopenharmony_ci qh->wait_expired = 0; 169862306a36Sopenharmony_ci qh->advance_jiffies = jiffies; 169962306a36Sopenharmony_ci goto done; 170062306a36Sopenharmony_ci } 170162306a36Sopenharmony_ci ret = uhci->is_stopped; 170262306a36Sopenharmony_ci } 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ci /* The queue hasn't advanced; check for timeout */ 170562306a36Sopenharmony_ci if (qh->wait_expired) 170662306a36Sopenharmony_ci goto done; 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_ci if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) { 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_ci /* Detect the Intel bug and work around it */ 171162306a36Sopenharmony_ci if (qh->post_td && qh_element(qh) == 171262306a36Sopenharmony_ci LINK_TO_TD(uhci, qh->post_td)) { 171362306a36Sopenharmony_ci qh->element = qh->post_td->link; 171462306a36Sopenharmony_ci qh->advance_jiffies = jiffies; 171562306a36Sopenharmony_ci ret = 1; 171662306a36Sopenharmony_ci goto done; 171762306a36Sopenharmony_ci } 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci qh->wait_expired = 1; 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_ci /* If the current URB wants FSBR, unlink it temporarily 172262306a36Sopenharmony_ci * so that we can safely set the next TD to interrupt on 172362306a36Sopenharmony_ci * completion. That way we'll know as soon as the queue 172462306a36Sopenharmony_ci * starts moving again. */ 172562306a36Sopenharmony_ci if (urbp && urbp->fsbr && !(status & TD_CTRL_IOC)) 172662306a36Sopenharmony_ci uhci_unlink_qh(uhci, qh); 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ci } else { 172962306a36Sopenharmony_ci /* Unmoving but not-yet-expired queues keep FSBR alive */ 173062306a36Sopenharmony_ci if (urbp) 173162306a36Sopenharmony_ci uhci_urbp_wants_fsbr(uhci, urbp); 173262306a36Sopenharmony_ci } 173362306a36Sopenharmony_ci 173462306a36Sopenharmony_cidone: 173562306a36Sopenharmony_ci return ret; 173662306a36Sopenharmony_ci} 173762306a36Sopenharmony_ci 173862306a36Sopenharmony_ci/* 173962306a36Sopenharmony_ci * Process events in the schedule, but only in one thread at a time 174062306a36Sopenharmony_ci */ 174162306a36Sopenharmony_cistatic void uhci_scan_schedule(struct uhci_hcd *uhci) 174262306a36Sopenharmony_ci{ 174362306a36Sopenharmony_ci int i; 174462306a36Sopenharmony_ci struct uhci_qh *qh; 174562306a36Sopenharmony_ci 174662306a36Sopenharmony_ci /* Don't allow re-entrant calls */ 174762306a36Sopenharmony_ci if (uhci->scan_in_progress) { 174862306a36Sopenharmony_ci uhci->need_rescan = 1; 174962306a36Sopenharmony_ci return; 175062306a36Sopenharmony_ci } 175162306a36Sopenharmony_ci uhci->scan_in_progress = 1; 175262306a36Sopenharmony_cirescan: 175362306a36Sopenharmony_ci uhci->need_rescan = 0; 175462306a36Sopenharmony_ci uhci->fsbr_is_wanted = 0; 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_ci uhci_clear_next_interrupt(uhci); 175762306a36Sopenharmony_ci uhci_get_current_frame_number(uhci); 175862306a36Sopenharmony_ci uhci->cur_iso_frame = uhci->frame_number; 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci /* Go through all the QH queues and process the URBs in each one */ 176162306a36Sopenharmony_ci for (i = 0; i < UHCI_NUM_SKELQH - 1; ++i) { 176262306a36Sopenharmony_ci uhci->next_qh = list_entry(uhci->skelqh[i]->node.next, 176362306a36Sopenharmony_ci struct uhci_qh, node); 176462306a36Sopenharmony_ci while ((qh = uhci->next_qh) != uhci->skelqh[i]) { 176562306a36Sopenharmony_ci uhci->next_qh = list_entry(qh->node.next, 176662306a36Sopenharmony_ci struct uhci_qh, node); 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_ci if (uhci_advance_check(uhci, qh)) { 176962306a36Sopenharmony_ci uhci_scan_qh(uhci, qh); 177062306a36Sopenharmony_ci if (qh->state == QH_STATE_ACTIVE) { 177162306a36Sopenharmony_ci uhci_urbp_wants_fsbr(uhci, 177262306a36Sopenharmony_ci list_entry(qh->queue.next, struct urb_priv, node)); 177362306a36Sopenharmony_ci } 177462306a36Sopenharmony_ci } 177562306a36Sopenharmony_ci } 177662306a36Sopenharmony_ci } 177762306a36Sopenharmony_ci 177862306a36Sopenharmony_ci uhci->last_iso_frame = uhci->cur_iso_frame; 177962306a36Sopenharmony_ci if (uhci->need_rescan) 178062306a36Sopenharmony_ci goto rescan; 178162306a36Sopenharmony_ci uhci->scan_in_progress = 0; 178262306a36Sopenharmony_ci 178362306a36Sopenharmony_ci if (uhci->fsbr_is_on && !uhci->fsbr_is_wanted && 178462306a36Sopenharmony_ci !uhci->fsbr_expiring) { 178562306a36Sopenharmony_ci uhci->fsbr_expiring = 1; 178662306a36Sopenharmony_ci mod_timer(&uhci->fsbr_timer, jiffies + FSBR_OFF_DELAY); 178762306a36Sopenharmony_ci } 178862306a36Sopenharmony_ci 178962306a36Sopenharmony_ci if (list_empty(&uhci->skel_unlink_qh->node)) 179062306a36Sopenharmony_ci uhci_clear_next_interrupt(uhci); 179162306a36Sopenharmony_ci else 179262306a36Sopenharmony_ci uhci_set_next_interrupt(uhci); 179362306a36Sopenharmony_ci} 1794