USB: fix handle NAK for IN/OUT SSPLIT/CSPLIT transfers.
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg_310 / dwc_otg_hcd_intr.c
index c803e39a22d6359b3ded67589ab529cecf8905cd..33018f4f285fdc011967c3348ca6469d6e124cca 100755 (executable)
@@ -832,6 +832,7 @@ static void release_channel(dwc_otg_hcd_t *hcd,
 {
        dwc_otg_transaction_type_e tr_type;
        int free_qtd;
+       int continue_trans = 1;
 
        DWC_DEBUGPL(DBG_HCDV, "  %s: channel %d, halt_status %d\n",
                    __func__, hc->hc_num, halt_status);
@@ -883,6 +884,7 @@ static void release_channel(dwc_otg_hcd_t *hcd,
                 * deactivated. Don't want to do anything except release the
                 * host channel and try to queue more transfers.
                 */
+               continue_trans = 0;
                goto cleanup;
        case DWC_OTG_HC_XFER_NO_HALT_STATUS:
                free_qtd = 0;
@@ -898,6 +900,10 @@ static void release_channel(dwc_otg_hcd_t *hcd,
                break;
        }
 
+       if (hc->csplit_nak) {
+               continue_trans = 0;
+               hc->csplit_nak = 0;
+       }
        deactivate_qh(hcd, hc->qh, free_qtd);
 
 cleanup:
@@ -925,9 +931,10 @@ cleanup:
        }
 
        /* Try to queue more transfers now that there's a free channel. */
-       tr_type = dwc_otg_hcd_select_transactions(hcd);
-       if (tr_type != DWC_OTG_TRANSACTION_NONE) {
-               dwc_otg_hcd_queue_transactions(hcd, tr_type);
+       if (continue_trans) {
+               tr_type = dwc_otg_hcd_select_transactions(hcd);
+               if (tr_type != DWC_OTG_TRANSACTION_NONE)
+                       dwc_otg_hcd_queue_transactions(hcd, tr_type);
        }
 }
 
@@ -1364,6 +1371,7 @@ static int32_t handle_hc_nak_intr(dwc_otg_hcd_t *hcd,
                if (hc->complete_split) {
                        qtd->error_count = 0;
                }
+               hc->csplit_nak = 1;
                qtd->complete_split = 0;
                halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
                goto handle_nak_done;