usb: dwc2: Update target (u)frame calculation
authorGrigor Tovmasyan <Grigor.Tovmasyan@synopsys.com>
Wed, 29 Aug 2018 17:00:33 +0000 (21:00 +0400)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Tue, 2 Oct 2018 07:49:50 +0000 (10:49 +0300)
In service interval based scheduling target (u)frame must be
set as a last frame in this the service interval.

Acked-by: Minas Harutyunyan <hminas@synopsys.com>
Signed-off-by: Grigor Tovmasyan <tovmasya@synopsys.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/dwc2/gadget.c

index 71f097d8900134db0e6f7ccc80958488ff8b4ff8..9de16453a890081cb16a3f1e210d7484cca71ba9 100644 (file)
@@ -2830,6 +2830,23 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep)
                if (using_desc_dma(hsotg)) {
                        hs_ep->target_frame = hsotg->frame_number;
                        dwc2_gadget_incr_frame_num(hs_ep);
+
+                       /* In service interval mode target_frame must
+                        * be set to last (u)frame of the service interval.
+                        */
+                       if (hsotg->params.service_interval) {
+                               /* Set target_frame to the first (u)frame of
+                                * the service interval
+                                */
+                               hs_ep->target_frame &= ~hs_ep->interval + 1;
+
+                               /* Set target_frame to the last (u)frame of
+                                * the service interval
+                                */
+                               dwc2_gadget_incr_frame_num(hs_ep);
+                               dwc2_gadget_dec_frame_num_by_one(hs_ep);
+                       }
+
                        dwc2_gadget_start_isoc_ddma(hs_ep);
                        return;
                }