Hi, On Mon, Aug 06, 2012 at 03:33:16PM +0530, Pratyush Anand wrote: > From: Pratyush ANAND <pratyush.anand@xxxxxx> > > We need to issue DEPCFG (with Config Action Set to "Modify") as per > specification. Even if we do not respect this , it works in normal > cases. But, I have observed one failure in very peculiar situation. > > If cpu clock is very slow and execution of connection done ISR takes > long time (may be around 150 mS), then one will never be able to > complete even first setup request. Setup bytes is received, but IN data > for get device descriptor is never observed on wire. dwc3 always keeps > on waiting for first data transfer complete event. > > It can easily be reproduced even when working with high cpu clock by > deliberately putting delay around 150-200 mS at the start of connection > done handler. > > Current patch corrects the error. > > Signed-off-by: Pratyush Anand <pratyush.anand@xxxxxx> this is wrong, you implement it with weird heuristics based on the endpoint state. All you needed to do was pass another argument to the set_ep_config() function like I did... > --- > drivers/usb/dwc3/core.h | 1 + > drivers/usb/dwc3/gadget.c | 9 +++++++++ > 2 files changed, 10 insertions(+), 0 deletions(-) > > diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h > index 133ed5a..e5b6496 100644 > --- a/drivers/usb/dwc3/core.h > +++ b/drivers/usb/dwc3/core.h > @@ -489,6 +489,7 @@ enum dwc3_link_state { > }; > > enum dwc3_device_state { > + DWC3_ATTACHED_STATE, this is not a USB-defined state, so I don't want to use it. > DWC3_DEFAULT_STATE, > DWC3_ADDRESS_STATE, > DWC3_CONFIGURED_STATE, > diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c > index f6ba644..3926095 100644 > --- a/drivers/usb/dwc3/gadget.c > +++ b/drivers/usb/dwc3/gadget.c > @@ -473,6 +473,9 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, > dep->interval = 1 << (desc->bInterval - 1); > } > > + if (dwc->dev_state != DWC3_ATTACHED_STATE) > + params.param0 |= DWC3_DEPCFG_ACTION_MODIFY; the modify action is not available on all versions of the core. On older versions of the core, this was called "Ignore Sequence Number bit". And this I have already patched, see below: commit 4b345c9a3c7452340fb477868d8db475f05978b1 Author: Felipe Balbi <balbi@xxxxxx> Date: Mon Jul 16 14:08:16 2012 +0300 usb: dwc3: gadget: set Ignore Sequence Number bit from ConnectDone Event Databook says we should set Ignore Sequence Number bit from ConnectDone Event, so let's do so. Signed-off-by: Felipe Balbi <balbi@xxxxxx> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 58fdfad..283c0cb 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -431,7 +431,8 @@ static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep) static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, const struct usb_endpoint_descriptor *desc, - const struct usb_ss_ep_comp_descriptor *comp_desc) + const struct usb_ss_ep_comp_descriptor *comp_desc, + bool ignore) { struct dwc3_gadget_ep_cmd_params params; @@ -441,6 +442,9 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc)) | DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst - 1); + if (ignore) + params.param0 |= DWC3_DEPCFG_IGN_SEQ_NUM; + params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN | DWC3_DEPCFG_XFER_NOT_READY_EN; @@ -498,7 +502,8 @@ static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep) */ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, const struct usb_endpoint_descriptor *desc, - const struct usb_ss_ep_comp_descriptor *comp_desc) + const struct usb_ss_ep_comp_descriptor *comp_desc, + bool ignore) { struct dwc3 *dwc = dep->dwc; u32 reg; @@ -510,7 +515,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, return ret; } - ret = dwc3_gadget_set_ep_config(dwc, dep, desc, comp_desc); + ret = dwc3_gadget_set_ep_config(dwc, dep, desc, comp_desc, ignore); if (ret) return ret; @@ -683,7 +688,7 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep, dev_vdbg(dwc->dev, "Enabling %s\n", dep->name); spin_lock_irqsave(&dwc->lock, flags); - ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc); + ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false); spin_unlock_irqrestore(&dwc->lock, flags); return ret; @@ -1518,14 +1523,14 @@ static int dwc3_gadget_start(struct usb_gadget *g, dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); dep = dwc->eps[0]; - ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); + ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false); if (ret) { dev_err(dwc->dev, "failed to enable %s\n", dep->name); goto err0; } dep = dwc->eps[1]; - ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); + ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false); if (ret) { dev_err(dwc->dev, "failed to enable %s\n", dep->name); goto err1; @@ -2141,14 +2146,14 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) } dep = dwc->eps[0]; - ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); + ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true); if (ret) { dev_err(dwc->dev, "failed to enable %s\n", dep->name); return; } dep = dwc->eps[1]; - ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); + ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true); if (ret) { dev_err(dwc->dev, "failed to enable %s\n", dep->name); return; I have sent this patch to linux-usb a while ago [1] [1] http://marc.info/?l=linux-usb&m=134303785528433&w=2 -- balbi
Attachment:
signature.asc
Description: Digital signature