Skip to content

host/dwc2: resume OUT transfer when PING ACKed #3077

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 18, 2025
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 20 additions & 13 deletions src/portable/synopsys/dwc2/hcd_dwc2.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ typedef struct {

struct TU_ATTR_PACKED {
uint32_t uframe_interval : 18; // micro-frame interval
uint32_t speed : 2;
uint32_t next_pid : 2;
uint32_t do_ping : 1;
uint32_t speed : 2;
uint32_t next_pid : 2; // PID for next transfer
uint32_t next_do_ping : 1; // Do PING for next transfer if possible (highspeed OUT)
// uint32_t : 9;
};

Expand Down Expand Up @@ -567,12 +567,12 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) {
hctsiz.pid = edpt->next_pid; // next PID is set in transfer complete interrupt
hctsiz.packet_count = packet_count;
hctsiz.xfer_size = edpt->buflen;
if (edpt->do_ping && edpt->speed == TUSB_SPEED_HIGH &&
if (edpt->next_do_ping && edpt->speed == TUSB_SPEED_HIGH &&
edpt->next_pid != HCTSIZ_PID_SETUP && hcchar_bm->ep_dir == TUSB_DIR_OUT) {
hctsiz.do_ping = 1;
}
channel->hctsiz = hctsiz.value;
edpt->do_ping = 0;
edpt->next_do_ping = 0;

// pre-calculate next PID based on packet count, adjusted in transfer complete interrupt if short packet
if (hcchar_bm->ep_num == 0) {
Expand Down Expand Up @@ -603,7 +603,7 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) {
hcintmsk |= HCINT_BABBLE_ERR | HCINT_DATATOGGLE_ERR | HCINT_ACK;
} else {
hcintmsk |= HCINT_NYET;
if (edpt->hcsplt_bm.split_en) {
if (edpt->hcsplt_bm.split_en || hctsiz.do_ping) {
hcintmsk |= HCINT_ACK;
}
}
Expand Down Expand Up @@ -970,7 +970,7 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t
channel->hcsplt = hcsplt.value;
channel->hcchar |= HCCHAR_CHENA;
} else {
edpt->do_ping = 1;
edpt->next_do_ping = 1;
channel_xfer_out_wrapup(dwc2, ch_id);
channel_disable(dwc2, channel);
}
Expand All @@ -983,7 +983,7 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t
channel->hcintmsk |= HCINT_ACK;
} else {
// NAK disable channel to flush all posted request and try again
edpt->do_ping = 1;
edpt->next_do_ping = 1;
xfer->err_count = 0;
}
} else if (hcint & HCINT_HALTED) {
Expand All @@ -1000,11 +1000,18 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t
} else if (hcint & HCINT_ACK) {
xfer->err_count = 0;
channel->hcintmsk &= ~HCINT_ACK;
if (hcsplt.split_en && !hcsplt.split_compl) {
// start split is ACK --> do complete split
hcsplt.split_compl = 1;
channel->hcsplt = hcsplt.value;
channel->hcchar |= HCCHAR_CHENA;
if (hcsplt.split_en) {
if (!hcsplt.split_compl) {
// start split is ACK --> do complete split
hcsplt.split_compl = 1;
channel->hcsplt = hcsplt.value;
channel->hcchar |= HCCHAR_CHENA;
}
} else {
// Device is ready, resume transfer
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need to use channel_xfer_start() since all meta data is setup, also it will toggle PID (causing data toggle error). Just enabled channel with channel->hcchar |= HCCHAR_CHENA; is good enough.

edpt->next_do_ping = 0;
xfer->err_count = 0;
TU_ASSERT(channel_xfer_start(dwc2, ch_id));
}
}

Expand Down
Loading