diff options
author | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2016-07-23 07:59:19 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2016-07-23 07:59:19 -0300 |
commit | c278256d05a2fc75b427fa6a5dc0024faa93465d (patch) | |
tree | 2c09c6c65a4b6c597a568ec2425adb75eff7d5d5 /drivers/usb/dwc2/gadget.c | |
parent | 7e5b7d1b3a8facd4dc1ddb5d9ec53c0687d13de7 (diff) | |
parent | 009a620848218d521f008141c62f56bf19294dd9 (diff) |
Merge branch 'patchwork' into topic/docs-next
* patchwork: (1492 commits)
[media] cec: always check all_device_types and features
[media] cec: poll should check if there is room in the tx queue
[media] vivid: support monitor all mode
[media] cec: fix test for unconfigured adapter in main message loop
[media] cec: limit the size of the transmit queue
[media] cec: zero unused msg part after msg->len
[media] cec: don't set fh to NULL in CEC_TRANSMIT
[media] cec: clear all status fields before transmit and always fill in sequence
[media] cec: CEC_RECEIVE overwrote the timeout field
[media] cxd2841er: Reading SNR for DVB-C added
[media] cxd2841er: Reading BER and UCB for DVB-C added
[media] cxd2841er: fix switch-case for DVB-C
[media] cxd2841er: fix signal strength scale for ISDB-T
[media] cxd2841er: adjust the dB scale for DVB-C
[media] cxd2841er: provide signal strength for DVB-C
[media] cxd2841er: fix BER report via DVBv5 stats API
[media] mb86a20s: apply mask to val after checking for read failure
[media] airspy: fix error logic during device register
[media] s5p-cec/TODO: add TODO item
[media] cec/TODO: drop comment about sphinx documentation
...
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/usb/dwc2/gadget.c')
-rw-r--r-- | drivers/usb/dwc2/gadget.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 4c5e3005e1dc..26cf09d0fe3c 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -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,17 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value) return 0; } + if (hs_ep->isochronous) { + dev_err(hs->dev, "%s is Isochronous Endpoint\n", ep->name); + return -EINVAL; + } + + 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 +3036,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; |