|
@@ -1018,7 +1018,7 @@ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
|
|
return 1;
|
|
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
|
|
* 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:
|
|
case USB_ENDPOINT_HALT:
|
|
halted = ep->halted;
|
|
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);
|
|
ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
|
|
if (ret) {
|
|
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
|
|
* dwc2_hsotg_ep_sethalt - set halt on a given endpoint
|
|
* @ep: The endpoint to set halt.
|
|
* @ep: The endpoint to set halt.
|
|
* @value: Set or unset the 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_ep *hs_ep = our_ep(ep);
|
|
struct dwc2_hsotg *hs = hs_ep->parent;
|
|
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;
|
|
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) {
|
|
if (hs_ep->dir_in) {
|
|
epreg = DIEPCTL(index);
|
|
epreg = DIEPCTL(index);
|
|
epctl = dwc2_readl(hs->regs + epreg);
|
|
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;
|
|
int ret = 0;
|
|
|
|
|
|
spin_lock_irqsave(&hs->lock, flags);
|
|
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);
|
|
spin_unlock_irqrestore(&hs->lock, flags);
|
|
|
|
|
|
return ret;
|
|
return ret;
|