static void ehci_mem_cleanup (struct ehci_hcd *ehci) { free_cached_lists(ehci); if (ehci->async) qh_put (ehci->async); ehci->async = NULL; /* DMA consistent memory and pools */ if (ehci->qtd_pool) dma_pool_destroy (ehci->qtd_pool); ehci->qtd_pool = NULL; if (ehci->qh_pool) { dma_pool_destroy (ehci->qh_pool); ehci->qh_pool = NULL; } if (ehci->itd_pool) dma_pool_destroy (ehci->itd_pool); ehci->itd_pool = NULL; if (ehci->sitd_pool) dma_pool_destroy (ehci->sitd_pool); ehci->sitd_pool = NULL; if (ehci->periodic) dma_free_coherent (ehci_to_hcd(ehci)->self.controller, ehci->periodic_size * sizeof (u32), ehci->periodic, ehci->periodic_dma); ehci->periodic = NULL; /* shadow periodic table */ kfree(ehci->pshadow); ehci->pshadow = NULL; }
static void ehci_mem_cleanup (struct ehci_hcd *ehci) { if (ehci->async) qh_put (ehci, ehci->async); ehci->async = 0; /* PCI consistent memory and pools */ if (ehci->qtd_pool) pci_pool_destroy (ehci->qtd_pool); ehci->qtd_pool = 0; if (ehci->qh_pool) { pci_pool_destroy (ehci->qh_pool); ehci->qh_pool = 0; } if (ehci->itd_pool) pci_pool_destroy (ehci->itd_pool); ehci->itd_pool = 0; if (ehci->sitd_pool) pci_pool_destroy (ehci->sitd_pool); ehci->sitd_pool = 0; if (ehci->periodic) pci_free_consistent (ehci->hcd.pdev, ehci->periodic_size * sizeof (u32), ehci->periodic, ehci->periodic_dma); ehci->periodic = 0; /* shadow periodic table */ if (ehci->pshadow) kfree (ehci->pshadow); ehci->pshadow = 0; }
static void ehci_urb_done ( struct ehci_hcd *ehci, dma_addr_t addr, struct urb *urb ) { if (urb->transfer_buffer_length) pci_unmap_single (ehci->hcd.pdev, addr, urb->transfer_buffer_length, usb_pipein (urb->pipe) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); if (likely (urb->hcpriv != 0)) { qh_put (ehci, (struct ehci_qh *) urb->hcpriv); urb->hcpriv = 0; } if (likely (urb->status == -EINPROGRESS)) { if (urb->actual_length != urb->transfer_buffer_length && (urb->transfer_flags & USB_DISABLE_SPD)) urb->status = -EREMOTEIO; else urb->status = 0; } /* hand off urb ownership */ usb_hcd_giveback_urb (&ehci->hcd, urb); }
static void ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); unsigned long flags; struct ehci_qh *qh, *tmp; /* ASSERT: any requests/urbs are being unlinked */ /* ASSERT: nobody can be submitting urbs for this any more */ rescan: spin_lock_irqsave (&ehci->lock, flags); qh = ep->hcpriv; if (!qh) goto done; /* endpoints can be iso streams. for now, we don't * accelerate iso completions ... so spin a while. */ if (qh->hw_info1 == 0) { ehci_vdbg (ehci, "iso delay\n"); goto idle_timeout; } if (!HC_IS_RUNNING (hcd->state)) qh->qh_state = QH_STATE_IDLE; switch (qh->qh_state) { case QH_STATE_LINKED: for (tmp = ehci->async->qh_next.qh; tmp && tmp != qh; tmp = tmp->qh_next.qh) continue; /* periodic qh self-unlinks on empty */ if (!tmp) goto nogood; unlink_async (ehci, qh); /* FALL THROUGH */ case QH_STATE_UNLINK: /* wait for hw to finish? */ case QH_STATE_UNLINK_WAIT: idle_timeout: spin_unlock_irqrestore (&ehci->lock, flags); schedule_timeout_uninterruptible(1); goto rescan; case QH_STATE_IDLE: /* fully unlinked */ if (list_empty (&qh->qtd_list)) { qh_put (qh); break; } /* else FALL THROUGH */ default: nogood: /* caller was supposed to have unlinked any requests; * that's not our job. just leak this memory. */ ehci_err (ehci, "qh %p (#%02x) state %d%s\n", qh, ep->desc.bEndpointAddress, qh->qh_state, list_empty (&qh->qtd_list) ? "" : "(has tds)"); break; } ep->hcpriv = NULL; done: spin_unlock_irqrestore (&ehci->lock, flags); return; }