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 <hminas@synopsys.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
This commit is contained in:
Minas Harutyunyan 2018-07-27 14:48:45 +04:00 committed by Felipe Balbi
parent fe369e1826
commit 4d4f1e79b8
1 changed files with 4 additions and 15 deletions

View File

@ -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));