From 4d4f1e79b800c80313280eec1af25a242a50dce5 Mon Sep 17 00:00:00 2001 From: Minas Harutyunyan Date: Fri, 27 Jul 2018 14:48:45 +0400 Subject: usb: dwc2: gadget: ISOC's starting flow improvement To start ISOC transfers in handlers dwc2_gadget_handle_nak() and dwc2_gadget_handle_out_token_ep_disabled() driver reads current frame number, based on which, set target frame number to start first ISOC transfer. In case if system's high IRQ latency and multiple EP's asserted interrupt in same frame, there are high probability that when reading current frame number in EP's handlers, actual frame number can be increased. As result for bInterval > 1, starting target frame will be set wrongly and all ISOC packets will be dropped. In patch "usb: dwc2: Change reading of current frame number flow" reading of current frame number done ASAP in common interrupt handler. This frame number stored in frame_number variable which used as starting frame number for ISOC EP's in above mentioned handlers. Signed-off-by: Minas Harutyunyan Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/gadget.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 26fdb4b60ff6..887bea99dce8 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -2750,21 +2750,14 @@ static void dwc2_gadget_handle_out_token_ep_disabled(struct dwc2_hsotg_ep *ep) struct dwc2_hsotg *hsotg = ep->parent; int dir_in = ep->dir_in; u32 doepmsk; - u32 tmp; if (dir_in || !ep->isochronous) return; - /* - * Store frame in which irq was asserted here, as - * it can change while completing request below. - */ - tmp = dwc2_hsotg_read_frameno(hsotg); - if (using_desc_dma(hsotg)) { if (ep->target_frame == TARGET_FRAME_INITIAL) { /* Start first ISO Out */ - ep->target_frame = tmp; + ep->target_frame = hsotg->frame_number; dwc2_gadget_start_isoc_ddma(ep); } return; @@ -2772,11 +2765,9 @@ static void dwc2_gadget_handle_out_token_ep_disabled(struct dwc2_hsotg_ep *ep) if (ep->interval > 1 && ep->target_frame == TARGET_FRAME_INITIAL) { - u32 dsts; u32 ctrl; - dsts = dwc2_readl(hsotg, DSTS); - ep->target_frame = dwc2_hsotg_read_frameno(hsotg); + ep->target_frame = hsotg->frame_number; dwc2_gadget_incr_frame_num(ep); ctrl = dwc2_readl(hsotg, DOEPCTL(ep->index)); @@ -2812,22 +2803,20 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep) { struct dwc2_hsotg *hsotg = hs_ep->parent; int dir_in = hs_ep->dir_in; - u32 tmp; if (!dir_in || !hs_ep->isochronous) return; if (hs_ep->target_frame == TARGET_FRAME_INITIAL) { - tmp = dwc2_hsotg_read_frameno(hsotg); if (using_desc_dma(hsotg)) { - hs_ep->target_frame = tmp; + hs_ep->target_frame = hsotg->frame_number; dwc2_gadget_incr_frame_num(hs_ep); dwc2_gadget_start_isoc_ddma(hs_ep); return; } - hs_ep->target_frame = tmp; + hs_ep->target_frame = hsotg->frame_number; if (hs_ep->interval > 1) { u32 ctrl = dwc2_readl(hsotg, DIEPCTL(hs_ep->index)); -- cgit v1.2.3