{
        struct dwc2_qtd *qtd;
        u32 max_xfer_size;
-       u16 idx, inc, n_desc, ntd_max = 0;
+       u16 idx, inc, n_desc = 0, ntd_max = 0;
+       u16 cur_idx;
+       u16 next_idx;
 
        idx = qh->td_last;
        inc = qh->interval;
-       n_desc = 0;
+       hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
+       cur_idx = dwc2_frame_list_idx(hsotg->frame_number);
+       next_idx = dwc2_desclist_idx_inc(qh->td_last, inc, qh->dev_speed);
+
+       /*
+        * Ensure current frame number didn't overstep last scheduled
+        * descriptor. If it happens, the only way to recover is to move
+        * qh->td_last to current frame number + 1.
+        * So that next isoc descriptor will be scheduled on frame number + 1
+        * and not on a past frame.
+        */
+       if (dwc2_frame_idx_num_gt(cur_idx, next_idx) || (cur_idx == next_idx)) {
+               if (inc < 32) {
+                       dev_vdbg(hsotg->dev,
+                                "current frame number overstep last descriptor\n");
+                       qh->td_last = dwc2_desclist_idx_inc(cur_idx, inc,
+                                                           qh->dev_speed);
+                       idx = qh->td_last;
+               }
+       }
 
        if (qh->interval) {
                ntd_max = (dwc2_max_desc_num(qh) + qh->interval - 1) /
                        MAX_ISOC_XFER_SIZE_HS : MAX_ISOC_XFER_SIZE_FS;
 
        list_for_each_entry(qtd, &qh->qtd_list, qtd_list_entry) {
+               if (qtd->in_process &&
+                   qtd->isoc_frame_index_last ==
+                   qtd->urb->packet_count)
+                       continue;
+
+               qtd->isoc_td_first = idx;
                while (qh->ntd < ntd_max && qtd->isoc_frame_index_last <
                                                qtd->urb->packet_count) {
                        dwc2_fill_host_isoc_dma_desc(hsotg, qtd, qh,
                        idx = dwc2_desclist_idx_inc(idx, inc, qh->dev_speed);
                        n_desc++;
                }
+               qtd->isoc_td_last = idx;
                qtd->in_process = 1;
        }