drivers/usb/mtu3/mtu3_qmu.c
Source file repositories/reference/linux-study-clean/drivers/usb/mtu3/mtu3_qmu.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/usb/mtu3/mtu3_qmu.c- Extension
.c- Size
- 18475 bytes
- Lines
- 687
- 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.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/dmapool.hlinux/iopoll.hmtu3.hmtu3_trace.h
Detected Declarations
function read_txq_cur_addrfunction read_rxq_cur_addrfunction write_txq_start_addrfunction write_rxq_start_addrfunction gpd_virt_to_dmafunction gpd_ring_initfunction reset_gpd_listfunction mtu3_gpd_ring_allocfunction mtu3_gpd_ring_freefunction mtu3_qmu_resumefunction gpd_ring_emptyfunction mtu3_prepare_transferfunction mtu3_prepare_tx_gpdfunction mtu3_prepare_rx_gpdfunction mtu3_insert_gpdfunction mtu3_qmu_startfunction mtu3_qmu_stopfunction mtu3_qmu_flushfunction qmu_tx_zlp_error_handlerfunction happensfunction qmu_done_txfunction qmu_done_rxfunction qmu_done_isrfunction qmu_exception_isrfunction mtu3_qmu_isrfunction mtu3_qmu_initfunction mtu3_qmu_exit
Annotated Snippet
if (mtu3_readl(mbase, USB_QMU_TQCSR(epnum)) & QMU_Q_ACTIVE) {
dev_warn(mtu->dev, "Tx %d Active Now!\n", epnum);
return 0;
}
mtu3_writel(mbase, USB_QMU_TQCSR(epnum), QMU_Q_START);
} else {
write_rxq_start_addr(mbase, epnum, ring->dma);
mtu3_setbits(mbase, MU3D_EP_RXCR0(epnum), RX_DMAREQEN);
/* don't expect ZLP */
mtu3_clrbits(mbase, U3D_QCR3, QMU_RX_ZLP(epnum));
/* move to next GPD when receive ZLP */
mtu3_setbits(mbase, U3D_QCR3, QMU_RX_COZ(epnum));
mtu3_writel(mbase, U3D_RQERRIESR0,
QMU_RX_LEN_ERR(epnum) | QMU_RX_CS_ERR(epnum));
mtu3_writel(mbase, U3D_RQERRIESR1, QMU_RX_ZLP_ERR(epnum));
if (mtu3_readl(mbase, USB_QMU_RQCSR(epnum)) & QMU_Q_ACTIVE) {
dev_warn(mtu->dev, "Rx %d Active Now!\n", epnum);
return 0;
}
mtu3_writel(mbase, USB_QMU_RQCSR(epnum), QMU_Q_START);
}
return 0;
}
/* may called in atomic context */
void mtu3_qmu_stop(struct mtu3_ep *mep)
{
struct mtu3 *mtu = mep->mtu;
void __iomem *mbase = mtu->mac_base;
int epnum = mep->epnum;
u32 value = 0;
u32 qcsr;
int ret;
qcsr = mep->is_in ? USB_QMU_TQCSR(epnum) : USB_QMU_RQCSR(epnum);
if (!(mtu3_readl(mbase, qcsr) & QMU_Q_ACTIVE)) {
dev_dbg(mtu->dev, "%s's qmu is inactive now!\n", mep->name);
return;
}
mtu3_writel(mbase, qcsr, QMU_Q_STOP);
if (mep->is_in)
mtu3_setbits(mbase, MU3D_EP_TXCR0(epnum), TX_FLUSHFIFO);
ret = readl_poll_timeout_atomic(mbase + qcsr, value,
!(value & QMU_Q_ACTIVE), 1, 1000);
if (ret) {
dev_err(mtu->dev, "stop %s's qmu failed\n", mep->name);
return;
}
/* flush fifo again to make sure the fifo is empty */
if (mep->is_in)
mtu3_setbits(mbase, MU3D_EP_TXCR0(epnum), TX_FLUSHFIFO);
dev_dbg(mtu->dev, "%s's qmu stop now!\n", mep->name);
}
void mtu3_qmu_flush(struct mtu3_ep *mep)
{
dev_dbg(mep->mtu->dev, "%s flush QMU %s\n", __func__,
((mep->is_in) ? "TX" : "RX"));
/*Stop QMU */
mtu3_qmu_stop(mep);
reset_gpd_list(mep);
}
/*
* QMU can't transfer zero length packet directly (a hardware limit
* on old SoCs), so when needs to send ZLP, we intentionally trigger
* a length error interrupt, and in the ISR sends a ZLP by BMU.
*/
static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum)
{
struct mtu3_ep *mep = mtu->in_eps + epnum;
struct mtu3_gpd_ring *ring = &mep->gpd_ring;
void __iomem *mbase = mtu->mac_base;
struct qmu_gpd *gpd_current = NULL;
struct mtu3_request *mreq;
dma_addr_t cur_gpd_dma;
u32 txcsr = 0;
int ret;
mreq = next_request(mep);
Annotation
- Immediate include surface: `linux/dmapool.h`, `linux/iopoll.h`, `mtu3.h`, `mtu3_trace.h`.
- Detected declarations: `function read_txq_cur_addr`, `function read_rxq_cur_addr`, `function write_txq_start_addr`, `function write_rxq_start_addr`, `function gpd_virt_to_dma`, `function gpd_ring_init`, `function reset_gpd_list`, `function mtu3_gpd_ring_alloc`, `function mtu3_gpd_ring_free`, `function mtu3_qmu_resume`.
- Atlas domain: Driver Families / drivers/usb.
- Implementation status: source implementation candidate.
- 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.