drivers/usb/chipidea/udc.c
Source file repositories/reference/linux-study-clean/drivers/usb/chipidea/udc.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/usb/chipidea/udc.c- Extension
.c- Size
- 59675 bytes
- Lines
- 2447
- 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.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/delay.hlinux/device.hlinux/dmapool.hlinux/dma-direct.hlinux/err.hlinux/irqreturn.hlinux/kernel.hlinux/slab.hlinux/pm_runtime.hlinux/pinctrl/consumer.hlinux/usb/ch9.hlinux/usb/gadget.hlinux/usb/otg-fsm.hlinux/usb/chipidea.hci.hudc.hbits.hotg.hotg_fsm.htrace.h
Detected Declarations
function hw_ep_bitfunction ep_to_bitfunction hw_device_statefunction hw_ep_flushfunction hw_ep_disablefunction hw_ep_enablefunction hw_ep_get_haltfunction hw_ep_primefunction hw_ep_set_haltfunction hw_port_is_high_speedfunction hw_test_and_clear_completefunction hw_test_and_clear_intr_activefunction hw_test_and_clear_setup_guardfunction hw_test_and_set_setup_guardfunction hw_usb_set_addressfunction hw_usb_resetfunction add_td_to_listfunction _usb_addrfunction prepare_td_for_non_sgfunction prepare_td_per_sgfunction ci_add_buffer_entryfunction prepare_td_for_sgfunction sglist_get_invalid_entryfunction sglist_do_bouncefunction sglist_do_debouncefunction _hardware_enqueuefunction free_pending_tdfunction reprime_dtdfunction _hardware_dequeuefunction list_for_each_entry_safefunction _ep_nukefunction list_for_each_entry_safefunction _ep_set_haltfunction _gadget_stop_activityfunction isr_reset_handlerfunction isr_get_status_completefunction _ep_queuefunction isr_get_status_responsefunction isr_setup_status_completefunction isr_setup_status_phasefunction isr_tr_complete_lowfunction list_for_each_entry_safefunction otg_a_alt_hnp_supportfunction isr_setup_packet_handlerfunction le16_to_cpufunction isr_tr_complete_handlerfunction usb_ep_enablefunction usb_ep_disable
Annotated Snippet
if (sg_dma_address(s) % PAGE_SIZE) {
dev_err(hwep->ci->dev, "not page aligned sg buffer\n");
return -EINVAL;
}
if (node && (node->td_remaining_size >= sg_dma_len(s))) {
ci_add_buffer_entry(node, s);
node->td_remaining_size -= sg_dma_len(s);
} else {
ret = prepare_td_per_sg(hwep, hwreq, s);
if (ret)
return ret;
node = list_entry(hwreq->tds.prev,
struct td_node, td);
}
s = sg_next(s);
}
return ret;
}
/*
* Verify if the scatterlist is valid by iterating each sg entry.
* Return invalid sg entry index which is less than num_sgs.
*/
static int sglist_get_invalid_entry(struct device *dma_dev, u8 dir,
struct usb_request *req)
{
int i;
struct scatterlist *s = req->sg;
if (req->num_sgs == 1)
return 1;
dir = dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
for (i = 0; i < req->num_sgs; i++, s = sg_next(s)) {
/* Only small sg (generally last sg) may be bounced. If
* that happens. we can't ensure the addr is page-aligned
* after dma map.
*/
if (dma_kmalloc_needs_bounce(dma_dev, s->length, dir))
break;
/* Make sure each sg start address (except first sg) is
* page-aligned and end address (except last sg) is also
* page-aligned.
*/
if (i == 0) {
if (!IS_ALIGNED(s->offset + s->length,
CI_HDRC_PAGE_SIZE))
break;
} else {
if (s->offset)
break;
if (!sg_is_last(s) && !IS_ALIGNED(s->length,
CI_HDRC_PAGE_SIZE))
break;
}
}
return i;
}
static int sglist_do_bounce(struct ci_hw_req *hwreq, int index,
bool copy, unsigned int *bounced)
{
void *buf;
int i, ret, nents, num_sgs;
unsigned int rest, rounded;
struct scatterlist *sg, *src, *dst;
nents = index + 1;
ret = sg_alloc_table(&hwreq->sgt, nents, GFP_KERNEL);
if (ret)
return ret;
sg = src = hwreq->req.sg;
num_sgs = hwreq->req.num_sgs;
rest = hwreq->req.length;
dst = hwreq->sgt.sgl;
for (i = 0; i < index; i++) {
memcpy(dst, src, sizeof(*src));
rest -= src->length;
src = sg_next(src);
dst = sg_next(dst);
}
Annotation
- Immediate include surface: `linux/delay.h`, `linux/device.h`, `linux/dmapool.h`, `linux/dma-direct.h`, `linux/err.h`, `linux/irqreturn.h`, `linux/kernel.h`, `linux/slab.h`.
- Detected declarations: `function hw_ep_bit`, `function ep_to_bit`, `function hw_device_state`, `function hw_ep_flush`, `function hw_ep_disable`, `function hw_ep_enable`, `function hw_ep_get_halt`, `function hw_ep_prime`, `function hw_ep_set_halt`, `function hw_port_is_high_speed`.
- 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.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
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.