diff options
| author | hathach <[email protected]> | 2026-06-13 00:18:32 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2026-06-13 23:34:57 +0700 |
| commit | b21d59f8177af967e2b2757c4ef996df00d1e617 (patch) | |
| tree | 201f6437338a416f947827f63bf6fded7d474f02 /src | |
| parent | 87eeab605ff571a5ac1784c2c26e944aa0129d7e (diff) | |
dcd/musb: replace deferral goto with per-state handling
The goto jumped into the csrl==0 completion switch with RXRDY still
set, making its "When CSRL0 is zero" guard comment untrue on that
path. Handle each deferral state in a self-contained switch instead;
the csrl==0 switch is now only reached with csrl==0 and its comment
is truthful again. Behavior unchanged.
Review follow-up for #3643 (dcd_musb.c l.523 finding).
Co-Authored-By: Claude Fable 5 <[email protected]>
Diffstat (limited to 'src')
| -rw-r--r-- | src/portable/mentor/musb/dcd_musb.c | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/src/portable/mentor/musb/dcd_musb.c b/src/portable/mentor/musb/dcd_musb.c index fdd2eaac9..9bdd6b080 100644 --- a/src/portable/mentor/musb/dcd_musb.c +++ b/src/portable/mentor/musb/dcd_musb.c @@ -510,20 +510,55 @@ static void process_ep0(uint8_t rhport) { // - Status IN/OUT finished, IRQ and new setup packet IRQ arrive at the same time. // - Data IN finished and status OUT is received, both IRQs and new setup packet IRQ arrive at the same time. // could happen when CPU load is high, save the new setup packet for later processing after current status stage complete. + case PIPE0_STATE_DATA_IN: case PIPE0_STATE_STATUS_OUT: case PIPE0_STATE_STATUS_OUT_PENDING: - case PIPE0_STATE_STATUS_IN: - case PIPE0_STATE_DATA_IN: { + case PIPE0_STATE_STATUS_IN: { TU_VERIFY(pipe0_read_setup(musb_regs, ep_csr, &_dcd.pipe0.deferred_setup), ); _dcd.pipe0.deferred_setup_valid = true; - goto process_status; + + switch (_dcd.pipe0.state) { + case PIPE0_STATE_DATA_IN: + // Last DATA IN packet sent (TXRDY-clear coalesced with the SETUP IRQ). The STATUS OUT + // confirm IRQ is missed too — promote so edpt0_xfer(STATUS OUT) fires complete immediately. + if (_dcd.pipe0.remain_wlength == 0) { + _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING; + } + dcd_event_xfer_complete(rhport, TU_EP0_IN, _dcd.pipe0.xact_len, XFER_RESULT_SUCCESS, true); + break; + + case PIPE0_STATE_STATUS_OUT: + // Status confirm IRQ coalesced with the SETUP — edpt0_xfer(STATUS OUT) fires complete. + _dcd.pipe0.state = PIPE0_STATE_STATUS_OUT_PENDING; + break; + + case PIPE0_STATE_STATUS_OUT_PENDING: + // edpt0_xfer(STATUS OUT) already called — fire complete and replay now. + _dcd.pipe0.state = PIPE0_STATE_IDLE; + dcd_event_xfer_complete(rhport, TU_EP0_OUT, 0, XFER_RESULT_SUCCESS, true); + pipe0_process_deferred_setup(rhport, ep_csr, true); + break; + + default: + // PIPE0_STATE_STATUS_IN: ZLP-sent IRQ coalesced with the SETUP. + if (_dcd.pipe0.pending_addr) { + musb_regs->faddr = _dcd.pipe0.pending_addr; + _dcd.pipe0.pending_addr = 0; + } + _dcd.pipe0.state = PIPE0_STATE_IDLE; + dcd_event_xfer_complete(rhport, TU_EP0_IN, 0, XFER_RESULT_SUCCESS, true); + pipe0_process_deferred_setup(rhport, ep_csr, true); + break; + } + break; } + + default: break; } return; } -process_status: /* When CSRL0 is zero, it means that either * - completion of sending any length packet TxPktRdy clear * - or status stage is complete (ZLP) after DataEnd is set */ |
