Hi Felipe, On 9 September 2016 at 19:03, Felipe Balbi <balbi@xxxxxxxxxx> wrote: > > Hi, > > Baolin Wang <baolin.wang@xxxxxxxxxx> writes: >> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c >> index 057739d..22787b6 100644 >> --- a/drivers/usb/dwc3/core.c >> +++ b/drivers/usb/dwc3/core.c >> @@ -999,6 +999,7 @@ static int dwc3_probe(struct platform_device *pdev) >> goto err0; >> >> spin_lock_init(&dwc->lock); >> + init_completion(&dwc->ep0_completed); > > this should be done only when gadget is required; meaning that this > should be moved to dwc3_gadget_init() OK. > >> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h >> index b2317e7..858e661 100644 >> --- a/drivers/usb/dwc3/core.h >> +++ b/drivers/usb/dwc3/core.h > > [...] > >> @@ -843,6 +844,7 @@ struct dwc3 { >> dma_addr_t ep0_bounce_addr; >> dma_addr_t scratch_addr; >> struct dwc3_request ep0_usb_req; >> + struct completion ep0_completed; > > when you call this "ep0_completed" it seems like you're defining a flag, > but you're not :) How about "ep0_in_setup" instead? That conveys the > idea that we're waiting for ep0 to reach setup phase. Make sense and will change it. > >> diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c >> index 632e5a4..baf932d 100644 >> --- a/drivers/usb/dwc3/ep0.c >> +++ b/drivers/usb/dwc3/ep0.c >> @@ -286,6 +286,7 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) >> >> dwc->ep0state = EP0_SETUP_PHASE; >> dwc3_ep0_out_start(dwc); >> + complete(&dwc->ep0_completed); > > no, this is wrong. I see what you're trying to do here, but we don't > want to duplicate this call to complete() right? One thing we can > realize is that *always* after STATUS phase or after a STALL, we will go > through dwc3_ep0_out_start(), this mean we can call complete() before > starting the following SETUP phase. > > Single place to call complete() ;-) Make sense to me and I will fix that in next version. > >> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c >> index 1a33308..c9026ce 100644 >> --- a/drivers/usb/dwc3/gadget.c >> +++ b/drivers/usb/dwc3/gadget.c >> @@ -1441,6 +1441,15 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) >> if (pm_runtime_suspended(dwc->dev)) >> return 0; >> >> + /* >> + * Per databook, when we want to stop the gadget, if a control transfer >> + * is still in process, complete it and get the core into setup phase. >> + */ >> + if (!is_on && dwc->ep0state != EP0_SETUP_PHASE) { >> + reinit_completion(&dwc->ep0_completed); > > this seems unnecessary to me. Also, why return here so the caller has to We should re-init the completion due to it will complete control transfer many times before we try to stop gadget. > wait? You could just have called wait_for_completion() here straight > away: > > if (!is_on && dwc->ep0state != EP0_SETUP_PHASE) { > /* should this be interruptible? */ > ret = wait_for_completion_timeout(&dwc->ep0_in_setup, > msecs_to_jiffies(500)); > if (ret == 0) { > dwc3_trace(trace_dwc3_gadget, "RUN/STOP timeout"); > return -ETIMEDOUT; > } > } > > There's also no need for that "try_again" trickery. We either can halt > the controller within 500ms or we cannot. But this is in atomic context and we can not issue wait_for_completion_timeout() in atomic context, then we should just return here. -- Baolin.wang Best Regards -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html