mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
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 https://github.com/raspberrypi/linux/issues/1709
This commit is contained in:
@@ -616,7 +616,7 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
|
||||
if (fiq_fsm_enable && (hcd->fiq_state->channel[n].fsm != FIQ_PASSTHROUGH)) {
|
||||
qh->channel->halt_status = DWC_OTG_HC_XFER_URB_DEQUEUE;
|
||||
qh->channel->halt_pending = 1;
|
||||
hcd->fiq_state->channel[n].fsm = FIQ_DEQUEUE_ISSUED;
|
||||
//hcd->fiq_state->channel[n].fsm = FIQ_DEQUEUE_ISSUED;
|
||||
} else {
|
||||
dwc_otg_hc_halt(hcd->core_if, qh->channel,
|
||||
DWC_OTG_HC_XFER_URB_DEQUEUE);
|
||||
@@ -634,6 +634,8 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
|
||||
hcd->core_if->dma_desc_enable?"DMA ":"");
|
||||
if (!hcd->core_if->dma_desc_enable) {
|
||||
uint8_t b = urb_qtd->in_process;
|
||||
if (nak_holdoff && qh->do_split && dwc_qh_is_non_per(qh))
|
||||
qh->nak_frame = 0xFFFF;
|
||||
dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh);
|
||||
if (b) {
|
||||
dwc_otg_hcd_qh_deactivate(hcd, qh, 0);
|
||||
|
||||
@@ -2382,15 +2382,17 @@ void dwc_otg_hcd_handle_hc_fsm(dwc_otg_hcd_t *hcd, uint32_t num)
|
||||
fiq_print(FIQDBG_INT, hcd->fiq_state, "OUT %01d %01d ", num , st->fsm);
|
||||
|
||||
hostchannels = hcd->available_host_channels;
|
||||
if (hc->halt_pending) {
|
||||
/* Dequeue: The FIQ was allowed to complete the transfer but state has been cleared. */
|
||||
release_channel(hcd, hc, NULL, hc->halt_status);
|
||||
return;
|
||||
}
|
||||
switch (st->fsm) {
|
||||
case FIQ_TEST:
|
||||
break;
|
||||
|
||||
case FIQ_DEQUEUE_ISSUED:
|
||||
/* hc_halt was called. QTD no longer exists. */
|
||||
/* TODO: for a nonperiodic split transaction, need to issue a
|
||||
* CLEAR_TT_BUFFER hub command if we were in the start-split phase.
|
||||
*/
|
||||
/* Handled above, but keep for posterity */
|
||||
release_channel(hcd, hc, NULL, hc->halt_status);
|
||||
break;
|
||||
|
||||
|
||||
@@ -793,6 +793,10 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
|
||||
/* Add back to inactive non-periodic schedule. */
|
||||
dwc_otg_hcd_qh_add(hcd, qh);
|
||||
//hcd->fiq_state->kick_np_queues = 1;
|
||||
} else {
|
||||
if(nak_holdoff && qh->do_split) {
|
||||
qh->nak_frame = 0xFFFF;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd);
|
||||
|
||||
Reference in New Issue
Block a user