diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c index 0eb335f4bc8ec3..4852d08d542f66 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c @@ -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); diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c index b2618c15d1f1f0..608e036be2c948 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c @@ -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; diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c index c2dff94e8e6edd..85a6d431ca54b4 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c @@ -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);