usb: dwc2: gadget: Do not halt endpoint if active
The gadget API function usb_ep_set_halt() expects the gadget to return -EAGAIN if the ep is active. Add support for this behavior. Otherwise this may break mass storage protocol if a STALL is attempted on the endpoint. Signed-off-by: Vahram Aharonyan <vahrama@synopsys.com> Signed-off-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
This commit is contained in:
parent
d246dcb233
commit
51da43b555
|
@ -1018,7 +1018,7 @@ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value);
|
||||
static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now);
|
||||
|
||||
/**
|
||||
* get_ep_head - return the first request on the endpoint
|
||||
|
@ -1094,7 +1094,7 @@ 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);
|
||||
dwc2_hsotg_ep_sethalt(&ep->ep, set, true);
|
||||
|
||||
ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
|
||||
if (ret) {
|
||||
|
@ -2948,8 +2948,13 @@ static int dwc2_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
|
|||
* dwc2_hsotg_ep_sethalt - set halt on a given endpoint
|
||||
* @ep: The endpoint to set halt.
|
||||
* @value: Set or unset the halt.
|
||||
* @now: If true, stall the endpoint now. Otherwise return -EAGAIN if
|
||||
* the endpoint is busy processing requests.
|
||||
*
|
||||
* We need to stall the endpoint immediately if request comes from set_feature
|
||||
* protocol command handler.
|
||||
*/
|
||||
static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value)
|
||||
static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now)
|
||||
{
|
||||
struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
|
||||
struct dwc2_hsotg *hs = hs_ep->parent;
|
||||
|
@ -2969,6 +2974,12 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!now && value && !list_empty(&hs_ep->queue)) {
|
||||
dev_dbg(hs->dev, "%s request is pending, cannot halt\n",
|
||||
ep->name);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (hs_ep->dir_in) {
|
||||
epreg = DIEPCTL(index);
|
||||
epctl = dwc2_readl(hs->regs + epreg);
|
||||
|
@ -3020,7 +3031,7 @@ static int dwc2_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value)
|
|||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&hs->lock, flags);
|
||||
ret = dwc2_hsotg_ep_sethalt(ep, value);
|
||||
ret = dwc2_hsotg_ep_sethalt(ep, value, false);
|
||||
spin_unlock_irqrestore(&hs->lock, flags);
|
||||
|
||||
return ret;
|
||||
|
|
Loading…
Reference in New Issue