Hi, John Youn <John.Youn@xxxxxxxxxxxx> writes: > The assignement of EP transfer resources was not handled properly in the > dwc3 driver. Commit aebda6187181 ("usb: dwc3: Reset the transfer > resource index on SET_INTERFACE") previously fixed one aspect of this > where resources may be exhausted with multiple calls to SET_INTERFACE. > However, it introduced an issue where composite devices with multiple > interfaces can be assigned the same transfer resources for different > endpoints. This patch solves both issues. > > The assignment of transfer resources cannot perfectly follow the data > book due to the fact that the controller driver does not have all > knowledge of the configuration in advance. It is given this information > piecemeal by the composite gadget framework after every > SET_CONFIGURATION and SET_INTERFACE. Trying to follow the databook > programming model in this scenario can cause errors. For two reasons: > > 1) The databook says to do DEPSTARTCFG for every SET_CONFIGURATION and > SET_INTERFACE (8.1.5). This is incorrect in the scenario of multiple > interfaces. > > 2) The databook does not mention doing more DEPXFERCFG for new endpoint > on alt setting (8.1.6). > > The following simplified method is used instead: > > All hardware endpoints can be assigned a transfer resource and this > setting will stay persistent until either a core reset or hibernation. > So whenever we do a DEPSTARTCFG(0) we can go ahead and do DEPXFERCFG for > every hardware endpoint as well. We are guaranteed that there are as > many transfer resources as endpoints. > > This patch triggers off of the calling dwc3_gadget_start_config() for > EP0-out, which always happens first, and which should only happen in one > of the above conditions. very good commit log. Thank you :-) > Fixes: aebda6187181 ("usb: dwc3: Reset the transfer resource index on SET_INTERFACE") you missed: Cc: <stable@xxxxxxxxxxxxxxx> # v.... > Reported-by: Ravi Babu <ravibabu@xxxxxx> > Signed-off-by: John Youn <johnyoun@xxxxxxxxxxxx> > --- > > Hi Ravi, > > This is a simplified version of the previous patch. Could you verify > that it works with your test scenario? > > Thanks, > John > > v2: > * Simplified assignment of resources by doing all endpoints at once. > > > drivers/usb/dwc3/core.h | 1 - > drivers/usb/dwc3/ep0.c | 5 ----- > drivers/usb/dwc3/gadget.c | 38 ++++++++++++++++++++------------------ > 3 files changed, 20 insertions(+), 24 deletions(-) > > diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h > index 2913068..e4f8b90 100644 > --- a/drivers/usb/dwc3/core.h > +++ b/drivers/usb/dwc3/core.h > @@ -856,7 +856,6 @@ struct dwc3 { > unsigned pullups_connected:1; > unsigned resize_fifos:1; > unsigned setup_packet_pending:1; > - unsigned start_config_issued:1; > unsigned three_stage_setup:1; > unsigned usb3_lpm_capable:1; > > diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c > index 3a9354a..8d6b75c 100644 > --- a/drivers/usb/dwc3/ep0.c > +++ b/drivers/usb/dwc3/ep0.c > @@ -555,7 +555,6 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) > int ret; > u32 reg; > > - dwc->start_config_issued = false; > cfg = le16_to_cpu(ctrl->wValue); > > switch (state) { > @@ -737,10 +736,6 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) > dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY"); > ret = dwc3_ep0_set_isoch_delay(dwc, ctrl); > break; > - case USB_REQ_SET_INTERFACE: > - dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_INTERFACE"); > - dwc->start_config_issued = false; > - /* Fall through */ > default: > dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver"); > ret = dwc3_ep0_delegate_req(dwc, ctrl); > diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c > index 7d1dd82..ae2e546 100644 > --- a/drivers/usb/dwc3/gadget.c > +++ b/drivers/usb/dwc3/gadget.c > @@ -385,24 +385,34 @@ static void dwc3_free_trb_pool(struct dwc3_ep *dep) > dep->trb_pool_dma = 0; > } > > +static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep); > + > static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep) > { > struct dwc3_gadget_ep_cmd_params params; > u32 cmd; > + int i, ret; I'd prefer if these two variables would be split into their own lines: int ret; int i; > + if (dep->number) > + return 0; > > memset(¶ms, 0x00, sizeof(params)); > + cmd = DWC3_DEPCMD_DEPSTARTCFG; > > - if (dep->number != 1) { > - cmd = DWC3_DEPCMD_DEPSTARTCFG; > - /* XferRscIdx == 0 for ep0 and 2 for the remaining */ > - if (dep->number > 1) { > - if (dwc->start_config_issued) > - return 0; > - dwc->start_config_issued = true; > - cmd |= DWC3_DEPCMD_PARAM(2); > - } > + ret = dwc3_send_gadget_ep_cmd(dwc, 0, cmd, ¶ms); > + if (ret) > + return ret; > + > + for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) { > + int epnum, dir; ditto. Also, (nit-picking, sorry) I'd prefer if the structure declaration would come first: struct dwc3_ep *dep = dwc->eps[i]; int epnum; int dir; also, do you mind adding a comment somewhere here explaining that we're not following the databook for a reason... It could be an almost carbon-copy of your commit log, actually. -- balbi
Attachment:
signature.asc
Description: PGP signature