int ret;
        int i;
 
-       if (list_empty(&dep->pending_list)) {
+       if (list_empty(&dep->pending_list) &&
+           list_empty(&dep->started_list)) {
                dep->flags |= DWC3_EP_PENDING_REQUEST;
                return -EAGAIN;
        }
                        break;
        }
 
+       /*
+        * After a number of unsuccessful start attempts due to bus-expiry
+        * status, issue END_TRANSFER command and retry on the next XferNotReady
+        * event.
+        */
+       if (ret == -EAGAIN) {
+               struct dwc3_gadget_ep_cmd_params params;
+               u32 cmd;
+
+               cmd = DWC3_DEPCMD_ENDTRANSFER |
+                       DWC3_DEPCMD_CMDIOC |
+                       DWC3_DEPCMD_PARAM(dep->resource_index);
+
+               dep->resource_index = 0;
+               memset(¶ms, 0, sizeof(params));
+
+               ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms);
+               if (!ret)
+                       dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
+       }
+
        return ret;
 }
 
                const struct dwc3_event_depevt *event)
 {
        dwc3_gadget_endpoint_frame_from_event(dep, event);
+
+       /*
+        * The XferNotReady event is generated only once before the endpoint
+        * starts. It will be generated again when END_TRANSFER command is
+        * issued. For some controller versions, the XferNotReady event may be
+        * generated while the END_TRANSFER command is still in process. Ignore
+        * it and wait for the next XferNotReady event after the command is
+        * completed.
+        */
+       if (dep->flags & DWC3_EP_END_TRANSFER_PENDING)
+               return;
+
        (void) __dwc3_gadget_start_isoc(dep);
 }