summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-06-13 00:18:32 +0700
committerhathach <[email protected]>2026-06-13 23:34:57 +0700
commitb21d59f8177af967e2b2757c4ef996df00d1e617 (patch)
tree201f6437338a416f947827f63bf6fded7d474f02 /src
parent87eeab605ff571a5ac1784c2c26e944aa0129d7e (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.c43
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 */