When a channel is halted because of urb dequeue during transfer
completion, no other qtds must be scheduled until halt is done.
Moreover, all in progress qtds must be given back.

Signed-off-by: Gregory Herrero <gregory.herr...@intel.com>
---
 drivers/usb/dwc2/hcd_ddma.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/hcd_ddma.c b/drivers/usb/dwc2/hcd_ddma.c
index 98d8627..5f72656 100644
--- a/drivers/usb/dwc2/hcd_ddma.c
+++ b/drivers/usb/dwc2/hcd_ddma.c
@@ -1161,6 +1161,21 @@ void dwc2_hcd_complete_xfer_ddma(struct dwc2_hsotg 
*hsotg,
                /* Release the channel if halted or session completed */
                if (halt_status != DWC2_HC_XFER_COMPLETE ||
                    list_empty(&qh->qtd_list)) {
+                       struct dwc2_qtd *qtd, *qtd_tmp;
+
+                       /*
+                        * Kill all remainings QTDs since channel has been
+                        * halted.
+                        */
+                       list_for_each_entry_safe(qtd, qtd_tmp,
+                                                &qh->qtd_list,
+                                                qtd_list_entry) {
+                               dwc2_host_complete(hsotg, qtd,
+                                                  -ECONNRESET);
+                               dwc2_hcd_qtd_unlink_and_free(hsotg,
+                                                            qtd, qh);
+                       }
+
                        /* Halt the channel if session completed */
                        if (halt_status == DWC2_HC_XFER_COMPLETE)
                                dwc2_hc_halt(hsotg, chan, halt_status);
@@ -1170,7 +1185,12 @@ void dwc2_hcd_complete_xfer_ddma(struct dwc2_hsotg 
*hsotg,
                        /* Keep in assigned schedule to continue transfer */
                        list_move(&qh->qh_list_entry,
                                  &hsotg->periodic_sched_assigned);
-                       continue_isoc_xfer = 1;
+                       /*
+                        * If channel has been halted during giveback of urb
+                        * then prevent any new scheduling.
+                        */
+                       if (!chan->halt_status)
+                               continue_isoc_xfer = 1;
                }
                /*
                 * Todo: Consider the case when period exceeds FrameList size.
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to