drivers/usb/host/ehci-q.c
Source file repositories/reference/linux-study-clean/drivers/usb/host/ehci-q.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/usb/host/ehci-q.c- Extension
.c- Size
- 43448 bytes
- Lines
- 1527
- Domain
- Driver Families
- Bucket
- drivers/usb
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
- No C-style include directives detected by the generator.
Detected Declarations
function Copyrightfunction qh_updatefunction togglefunction recoveryfunction qh_completionsfunction ehci_clear_tt_buffer_completefunction ehci_clear_tt_bufferfunction qtd_copy_statusfunction ehci_urb_donefunction qh_completionsfunction faultsfunction transfersfunction qtdfunction bufferfunction qtd_list_freefunction list_for_each_safefunction qh_urb_transactionfunction maskfunction enable_asyncfunction disable_asyncfunction qh_link_asyncfunction TDsfunction qh_refreshfunction submit_asyncfunction ehci_submit_single_step_set_featurefunction stagefunction single_unlink_asyncfunction start_iaa_cyclefunction end_iaa_cyclefunction end_unlink_asyncfunction Intelfunction unlink_empty_asyncfunction unlink_empty_async_suspendedfunction start_unlink_asyncfunction scan_asyncfunction BIT
Annotated Snippet
if (unlikely(!usb_gettoggle(qh->ps.udev, epnum, is_out))) {
hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
usb_settoggle(qh->ps.udev, epnum, is_out, 1);
}
}
hw->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
}
/* if it weren't for a common silicon quirk (writing the dummy into the qh
* overlay, so qh->hw_token wrongly becomes inactive/halted), only fault
* recovery (including urb dequeue) would need software changes to a QH...
*/
static void
qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
struct ehci_qtd *qtd;
qtd = list_entry(qh->qtd_list.next, struct ehci_qtd, qtd_list);
/*
* first qtd may already be partially processed.
* If we come here during unlink, the QH overlay region
* might have reference to the just unlinked qtd. The
* qtd is updated in qh_completions(). Update the QH
* overlay here.
*/
if (qh->hw->hw_token & ACTIVE_BIT(ehci)) {
qh->hw->hw_qtd_next = qtd->hw_next;
if (qh->should_be_inactive)
ehci_warn(ehci, "qh %p should be inactive!\n", qh);
} else {
qh_update(ehci, qh, qtd);
}
qh->should_be_inactive = 0;
}
/*-------------------------------------------------------------------------*/
static void qh_link_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd,
struct usb_host_endpoint *ep)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct ehci_qh *qh = ep->hcpriv;
unsigned long flags;
spin_lock_irqsave(&ehci->lock, flags);
qh->clearing_tt = 0;
if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list)
&& ehci->rh_state == EHCI_RH_RUNNING)
qh_link_async(ehci, qh);
spin_unlock_irqrestore(&ehci->lock, flags);
}
static void ehci_clear_tt_buffer(struct ehci_hcd *ehci, struct ehci_qh *qh,
struct urb *urb, u32 token)
{
/* If an async split transaction gets an error or is unlinked,
* the TT buffer may be left in an indeterminate state. We
* have to clear the TT buffer.
*
* Note: this routine is never called for Isochronous transfers.
*/
if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) {
#ifdef CONFIG_DYNAMIC_DEBUG
struct usb_device *tt = urb->dev->tt->hub;
dev_dbg(&tt->dev,
"clear tt buffer port %d, a%d ep%d t%08x\n",
urb->dev->ttport, urb->dev->devnum,
usb_pipeendpoint(urb->pipe), token);
#endif /* CONFIG_DYNAMIC_DEBUG */
if (!ehci_is_TDI(ehci)
|| urb->dev->tt->hub !=
ehci_to_hcd(ehci)->self.root_hub) {
if (usb_hub_clear_tt_buffer(urb) == 0)
qh->clearing_tt = 1;
} else {
/* REVISIT ARC-derived cores don't clear the root
* hub TT buffer in this way...
*/
}
}
}
static int qtd_copy_status (
struct ehci_hcd *ehci,
Annotation
- Detected declarations: `function Copyright`, `function qh_update`, `function toggle`, `function recovery`, `function qh_completions`, `function ehci_clear_tt_buffer_complete`, `function ehci_clear_tt_buffer`, `function qtd_copy_status`, `function ehci_urb_done`, `function qh_completions`.
- Atlas domain: Driver Families / drivers/usb.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.