On 5/5/2018 5:46 PM, Artur Petrosyan wrote:
> The current frame_number is read from core for both
> device and host modes. Reading of the current frame
> number needs to be performed ASAP due to IRQ latency's.
> This is why, it is moved to common interrupt handler.
> 
> Accordingly updated dwc2_gadget_target_frame_elapsed()
> function which uses stored frame_number instead of
> reading frame number.
> 
> In cases when target frame value is incremented
> the frame_number is required to read again.
> 
> Signed-off-by: Artur Petrosyan <[email protected]>
> ---

Acked-by: Minas Harutyunyan <[email protected]>

>   drivers/usb/dwc2/core.h      |  7 ++++---
>   drivers/usb/dwc2/core_intr.c |  8 ++++++++
>   drivers/usb/dwc2/gadget.c    | 13 +++++++++++--
>   3 files changed, 23 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
> index d83be5651f87..a435db4fe948 100644
> --- a/drivers/usb/dwc2/core.h
> +++ b/drivers/usb/dwc2/core.h
> @@ -813,6 +813,9 @@ struct dwc2_hregs_backup {
>    * @gadget_enabled  Peripheral mode sub-driver initialization indicator.
>    * @ll_hw_enabled   Status of low-level hardware resources.
>    * @hibernated:             True if core is hibernated
> + * @frame_number:       Frame number read from the core. For both device
> + *                   and host modes. The value ranges are from 0
> + *                   to HFNUM_MAX_FRNUM.
>    * @phy:                The otg phy transceiver structure for phy control.
>    * @uphy:               The otg phy transceiver structure for old USB phy
>    *                      control.
> @@ -886,8 +889,6 @@ struct dwc2_hregs_backup {
>    * @hs_periodic_bitmap: Bitmap used by the microframe scheduler any time the
>    *                      host is in high speed mode; low speed schedules are
>    *                      stored elsewhere since we need one per TT.
> - * @frame_number:       Frame number read from the core at SOF. The value 
> ranges
> - *                      from 0 to HFNUM_MAX_FRNUM.
>    * @periodic_qh_count:  Count of periodic QHs, if using several eps. Used 
> for
>    *                      SOF enable/disable.
>    * @free_hc_list:       Free host channels in the controller. This is a 
> list of
> @@ -954,6 +955,7 @@ struct dwc2_hsotg {
>       unsigned int gadget_enabled:1;
>       unsigned int ll_hw_enabled:1;
>       unsigned int hibernated:1;
> +     u16 frame_number;
>   
>       struct phy *phy;
>       struct usb_phy *uphy;
> @@ -1027,7 +1029,6 @@ struct dwc2_hsotg {
>       u16 periodic_usecs;
>       unsigned long hs_periodic_bitmap[
>               DIV_ROUND_UP(DWC2_HS_SCHEDULE_US, BITS_PER_LONG)];
> -     u16 frame_number;
>       u16 periodic_qh_count;
>       bool bus_suspended;
>       bool new_connection;
> diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
> index 2982a155734d..cc90b58b6b3c 100644
> --- a/drivers/usb/dwc2/core_intr.c
> +++ b/drivers/usb/dwc2/core_intr.c
> @@ -778,6 +778,14 @@ irqreturn_t dwc2_handle_common_intr(int irq, void *dev)
>               goto out;
>       }
>   
> +     /* Reading current frame number value in device or host modes. */
> +     if (dwc2_is_device_mode(hsotg))
> +             hsotg->frame_number = (dwc2_readl(hsotg->regs + DSTS)
> +                                    & DSTS_SOFFN_MASK) >> DSTS_SOFFN_SHIFT;
> +     else
> +             hsotg->frame_number = (dwc2_readl(hsotg->regs + HFNUM)
> +                                    & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT;
> +
>       gintsts = dwc2_read_common_intr(hsotg);
>       if (gintsts & ~GINTSTS_PRTINT)
>               retval = IRQ_HANDLED;
> diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
> index 6c32bf26e48e..f7343cda3234 100644
> --- a/drivers/usb/dwc2/gadget.c
> +++ b/drivers/usb/dwc2/gadget.c
> @@ -1235,7 +1235,7 @@ static bool dwc2_gadget_target_frame_elapsed(struct 
> dwc2_hsotg_ep *hs_ep)
>   {
>       struct dwc2_hsotg *hsotg = hs_ep->parent;
>       u32 target_frame = hs_ep->target_frame;
> -     u32 current_frame = dwc2_hsotg_read_frameno(hsotg);
> +     u32 current_frame = hsotg->frame_number;
>       bool frame_overrun = hs_ep->frame_overrun;
>   
>       if (!frame_overrun && current_frame >= target_frame)
> @@ -1350,8 +1350,15 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, 
> struct usb_request *req,
>                       return 0;
>               }
>   
> -             while (dwc2_gadget_target_frame_elapsed(hs_ep))
> +             /* Update current frame number value. */
> +             hs->frame_number = dwc2_hsotg_read_frameno(hs);
> +             while (dwc2_gadget_target_frame_elapsed(hs_ep)) {
>                       dwc2_gadget_incr_frame_num(hs_ep);
> +                     /* Update current frame number value once more as it
> +                      * changes here.
> +                      */
> +                     hs->frame_number = dwc2_hsotg_read_frameno(hs);
> +             }
>   
>               if (hs_ep->target_frame != TARGET_FRAME_INITIAL)
>                       dwc2_hsotg_start_req(hs, hs_ep, hs_req, false);
> @@ -2731,6 +2738,8 @@ static void dwc2_gadget_handle_ep_disabled(struct 
> dwc2_hsotg_ep *hs_ep)
>                       dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req,
>                                                   -ENODATA);
>               dwc2_gadget_incr_frame_num(hs_ep);
> +             /* Update current frame number value. */
> +             hsotg->frame_number = dwc2_hsotg_read_frameno(hsotg);
>       } while (dwc2_gadget_target_frame_elapsed(hs_ep));
>   
>       dwc2_gadget_start_next_request(hs_ep);
> 

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

Reply via email to