diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 7b6eb0ad513b..96b6935dc0d7 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -2748,6 +2748,8 @@ static int dwc2_assign_and_init_hc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) chan->xfer_len = urb->length - urb->actual_length; chan->xfer_count = 0; + chan->csplit_nak = 0; + /* Set the split attributes if required */ if (qh->do_split) dwc2_hc_init_split(hsotg, chan, qtd, urb); diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h index 78e9e01051b5..e54f1351225b 100644 --- a/drivers/usb/dwc2/hcd.h +++ b/drivers/usb/dwc2/hcd.h @@ -143,6 +143,7 @@ struct dwc2_host_chan { u8 halt_pending; u8 do_split; u8 complete_split; + u8 csplit_nak; u8 hub_addr; u8 hub_port; u8 xact_pos; diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index 916d991b96b8..551cfacd2252 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -691,6 +691,7 @@ static void dwc2_release_channel(struct dwc2_hsotg *hsotg, enum dwc2_transaction_type tr_type; u32 haintmsk; int free_qtd = 0; + int continue_trans = 1; if (dbg_hc(chan)) dev_vdbg(hsotg->dev, " %s: channel %d, halt_status %d\n", @@ -719,6 +720,7 @@ static void dwc2_release_channel(struct dwc2_hsotg *hsotg, * deactivated. Don't want to do anything except release the * host channel and try to queue more transfers. */ + continue_trans = 0; goto cleanup; case DWC2_HC_XFER_PERIODIC_INCOMPLETE: dev_vdbg(hsotg->dev, " Complete URB with I/O error\n"); @@ -730,6 +732,11 @@ static void dwc2_release_channel(struct dwc2_hsotg *hsotg, break; } + if (chan->csplit_nak) { + continue_trans = 0; + chan->csplit_nak = 0; + } + dwc2_deactivate_qh(hsotg, chan->qh, free_qtd); cleanup: @@ -767,9 +774,11 @@ static void dwc2_release_channel(struct dwc2_hsotg *hsotg, dwc2_writel(haintmsk, hsotg->regs + HAINTMSK); /* Try to queue more transfers now that there's a free channel */ - tr_type = dwc2_hcd_select_transactions(hsotg); - if (tr_type != DWC2_TRANSACTION_NONE) - dwc2_hcd_queue_transactions(hsotg, tr_type); + if (continue_trans) { + tr_type = dwc2_hcd_select_transactions(hsotg); + if (tr_type != DWC2_TRANSACTION_NONE) + dwc2_hcd_queue_transactions(hsotg, tr_type); + } } /* @@ -1205,6 +1214,7 @@ static void dwc2_hc_nak_intr(struct dwc2_hsotg *hsotg, if (chan->do_split) { if (chan->complete_split) qtd->error_count = 0; + chan->csplit_nak = 1; qtd->complete_split = 0; dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_NAK); goto handle_nak_done; -- 2.11.0