Message ID | a5dc0436-e40b-4115-bc1f-d169ac4f1881@US01WEHTC1.internal.synopsys.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | usb: dwc3: gadget: Handle 0 xfer length for OUT EP | expand |
Hi, Tejas Joglekar <tejas.joglekar@synopsys.com> writes: > For OUT endpoints, zero-length transfers require MaxPacketSize buffer as > per the DWC_usb3 programming guide 3.30a section 4.2.3.3. > > This patch fixes this by explicitly checking zero length > transfer to correctly pad up to MaxPacketSize. > > Signed-off-by: Tejas Joglekar <joglekar@synopsys.com> do you have tracepoints of the problem? > --- > drivers/usb/dwc3/gadget.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c > index e2caf9e..f1089ec 100644 > --- a/drivers/usb/dwc3/gadget.c > +++ b/drivers/usb/dwc3/gadget.c > @@ -1069,7 +1069,8 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, > if (sg_is_last(s)) > chain = false; > > - if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) { > + if ((!length || rem) && usb_endpoint_dir_out(dep->endpoint.desc) > + && !chain) { are you 100% certain we have scatter/gather for a zlp? That doesn't make sense to me. > @@ -1114,7 +1115,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, > unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); > unsigned int rem = length % maxp; > > - if (rem && usb_endpoint_dir_out(dep->endpoint.desc)) { > + if ((!length || rem) && usb_endpoint_dir_out(dep->endpoint.desc)) { this is already taken care of: > static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, > struct dwc3_request *req) > { > unsigned int length = req->request.length; > unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); > unsigned int rem = length % maxp; > > if (rem && usb_endpoint_dir_out(dep->endpoint.desc)) { [...] > } else if (req->request.zero && req->request.length && > (IS_ALIGNED(req->request.length, maxp))) { why isn't this branch triggering for you? Please capture and share tracepoints exposing the problem > struct dwc3 *dwc = dep->dwc; > struct dwc3_trb *trb; > > req->needs_extra_trb = true; > > /* prepare normal TRB */ > dwc3_prepare_one_trb(dep, req, true, 0); > > /* Now prepare one extra TRB to handle ZLP */ > trb = &dep->trb_pool[dep->trb_enqueue]; > req->num_trbs++; > __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, > false, 1, req->request.stream_id, > req->request.short_not_ok, > req->request.no_interrupt); > } else { > dwc3_prepare_one_trb(dep, req, false, 0); > } > }
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index e2caf9e..f1089ec 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1069,7 +1069,8 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, if (sg_is_last(s)) chain = false; - if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) { + if ((!length || rem) && usb_endpoint_dir_out(dep->endpoint.desc) + && !chain) { struct dwc3 *dwc = dep->dwc; struct dwc3_trb *trb; @@ -1114,7 +1115,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); unsigned int rem = length % maxp; - if (rem && usb_endpoint_dir_out(dep->endpoint.desc)) { + if ((!length || rem) && usb_endpoint_dir_out(dep->endpoint.desc)) { struct dwc3 *dwc = dep->dwc; struct dwc3_trb *trb;
For OUT endpoints, zero-length transfers require MaxPacketSize buffer as per the DWC_usb3 programming guide 3.30a section 4.2.3.3. This patch fixes this by explicitly checking zero length transfer to correctly pad up to MaxPacketSize. Signed-off-by: Tejas Joglekar <joglekar@synopsys.com> --- drivers/usb/dwc3/gadget.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)