diff options
author | Minas Harutyunyan <Minas.Harutyunyan@synopsys.com> | 2021-07-12 13:05:23 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-07-21 10:07:06 +0200 |
commit | b833ce15ce33a6e6b1d729fc78af79362aa8681e (patch) | |
tree | 5133b6a04106d1252f6413f121daa09e149957d5 /drivers/usb/dwc2/gadget.c | |
parent | usb: gadget: composite: Allow bMaxPower=0 if self-powered (diff) | |
download | linux-b833ce15ce33a6e6b1d729fc78af79362aa8681e.tar.xz linux-b833ce15ce33a6e6b1d729fc78af79362aa8681e.zip |
usb: dwc2: gadget: Add endpoint wedge support
Add enpoint wedge support. Tested by USBCV MSC tests.
Signed-off-by: Argishti Aleksanyan <Argishti.Aleksanyan@synopsys.com>
Signed-off-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
Link: https://lore.kernel.org/r/3143ea6b8eee08761709a6c2788216292be46a34.1626087390.git.Minas.Harutyunyan@synopsys.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/dwc2/gadget.c')
-rw-r--r-- | drivers/usb/dwc2/gadget.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index c581ee41ac81..fe567069dcb2 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -1806,7 +1806,8 @@ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg, case USB_ENDPOINT_HALT: halted = ep->halted; - dwc2_hsotg_ep_sethalt(&ep->ep, set, true); + if (!ep->wedged) + dwc2_hsotg_ep_sethalt(&ep->ep, set, true); ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0); if (ret) { @@ -4046,6 +4047,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, hs_ep->isochronous = 0; hs_ep->periodic = 0; hs_ep->halted = 0; + hs_ep->wedged = 0; hs_ep->interval = desc->bInterval; switch (ep_type) { @@ -4287,6 +4289,27 @@ static int dwc2_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) } /** + * dwc2_gadget_ep_set_wedge - set wedge on a given endpoint + * @ep: The endpoint to be wedged. + * + */ +static int dwc2_gadget_ep_set_wedge(struct usb_ep *ep) +{ + struct dwc2_hsotg_ep *hs_ep = our_ep(ep); + struct dwc2_hsotg *hs = hs_ep->parent; + + unsigned long flags; + int ret; + + spin_lock_irqsave(&hs->lock, flags); + hs_ep->wedged = 1; + ret = dwc2_hsotg_ep_sethalt(ep, 1, false); + spin_unlock_irqrestore(&hs->lock, flags); + + return ret; +} + +/** * dwc2_hsotg_ep_sethalt - set halt on a given endpoint * @ep: The endpoint to set halt. * @value: Set or unset the halt. @@ -4337,6 +4360,7 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now) epctl |= DXEPCTL_EPDIS; } else { epctl &= ~DXEPCTL_STALL; + hs_ep->wedged = 0; xfertype = epctl & DXEPCTL_EPTYPE_MASK; if (xfertype == DXEPCTL_EPTYPE_BULK || xfertype == DXEPCTL_EPTYPE_INTERRUPT) @@ -4353,6 +4377,7 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now) // STALL bit will be set in GOUTNAKEFF interrupt handler } else { epctl &= ~DXEPCTL_STALL; + hs_ep->wedged = 0; xfertype = epctl & DXEPCTL_EPTYPE_MASK; if (xfertype == DXEPCTL_EPTYPE_BULK || xfertype == DXEPCTL_EPTYPE_INTERRUPT) @@ -4392,6 +4417,7 @@ static const struct usb_ep_ops dwc2_hsotg_ep_ops = { .queue = dwc2_hsotg_ep_queue_lock, .dequeue = dwc2_hsotg_ep_dequeue, .set_halt = dwc2_hsotg_ep_sethalt_lock, + .set_wedge = dwc2_gadget_ep_set_wedge, /* note, don't believe we have any call for the fifo routines */ }; |