Skip to content

Commit 5ca413b

Browse files
P33Mpopcornmix
P33M
authored andcommitted
dwc_otg: make nak_holdoff work as intended with empty queues
If URBs reading from non-periodic split endpoints were dequeued and the last transfer from the endpoint was a NAK handshake, the resulting qh->nak_frame value was stale which would result in unnecessarily long polling intervals for the first subsequent transfer with a fresh URB. Fixup qh->nak_frame in dwc_otg_hcd_urb_dequeue and also guard against a case where a single URB is submitted to the endpoint, a NAK was received on the transfer immediately prior to receiving data and the device subsequently resubmits another URB past the qh->nak_frame interval. Fixes #1709
1 parent ef3b440 commit 5ca413b

File tree

3 files changed

+13
-5
lines changed

3 files changed

+13
-5
lines changed

drivers/usb/host/dwc_otg/dwc_otg_hcd.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
616616
if (fiq_fsm_enable && (hcd->fiq_state->channel[n].fsm != FIQ_PASSTHROUGH)) {
617617
qh->channel->halt_status = DWC_OTG_HC_XFER_URB_DEQUEUE;
618618
qh->channel->halt_pending = 1;
619-
hcd->fiq_state->channel[n].fsm = FIQ_DEQUEUE_ISSUED;
619+
//hcd->fiq_state->channel[n].fsm = FIQ_DEQUEUE_ISSUED;
620620
} else {
621621
dwc_otg_hc_halt(hcd->core_if, qh->channel,
622622
DWC_OTG_HC_XFER_URB_DEQUEUE);
@@ -634,6 +634,8 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
634634
hcd->core_if->dma_desc_enable?"DMA ":"");
635635
if (!hcd->core_if->dma_desc_enable) {
636636
uint8_t b = urb_qtd->in_process;
637+
if (nak_holdoff && qh->do_split && dwc_qh_is_non_per(qh))
638+
qh->nak_frame = 0xFFFF;
637639
dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
638640
if (b) {
639641
dwc_otg_hcd_qh_deactivate(hcd, qh, 0);

drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2382,15 +2382,17 @@ void dwc_otg_hcd_handle_hc_fsm(dwc_otg_hcd_t *hcd, uint32_t num)
23822382
fiq_print(FIQDBG_INT, hcd->fiq_state, "OUT %01d %01d ", num , st->fsm);
23832383

23842384
hostchannels = hcd->available_host_channels;
2385+
if (hc->halt_pending) {
2386+
/* Dequeue: The FIQ was allowed to complete the transfer but state has been cleared. */
2387+
release_channel(hcd, hc, NULL, hc->halt_status);
2388+
return;
2389+
}
23852390
switch (st->fsm) {
23862391
case FIQ_TEST:
23872392
break;
23882393

23892394
case FIQ_DEQUEUE_ISSUED:
2390-
/* hc_halt was called. QTD no longer exists. */
2391-
/* TODO: for a nonperiodic split transaction, need to issue a
2392-
* CLEAR_TT_BUFFER hub command if we were in the start-split phase.
2393-
*/
2395+
/* Handled above, but keep for posterity */
23942396
release_channel(hcd, hc, NULL, hc->halt_status);
23952397
break;
23962398

drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,10 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
793793
/* Add back to inactive non-periodic schedule. */
794794
dwc_otg_hcd_qh_add(hcd, qh);
795795
//hcd->fiq_state->kick_np_queues = 1;
796+
} else {
797+
if(nak_holdoff && qh->do_split) {
798+
qh->nak_frame = 0xFFFF;
799+
}
796800
}
797801
} else {
798802
uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd);

0 commit comments

Comments
 (0)