USB: dwc3-msm: Check endpoint status and request queued or not first

When function driver calls dwc3_msm_ep_queue() to queue endless request,
first check endpoint status and whether any request already queued or not.
If that is the case, return error. Else go ahead with queuing request
to USB HW. This helps in resolving the crash seen when request is being
queued again.

Change-Id: I3d6a603c693d1df36719f57684ffad409e1a0e78
Signed-off-by: Vijayavardhan Vennapusa <vvreddy@codeaurora.org>
Signed-off-by: Chandana Kishori Chiluveru <cchiluve@codeaurora.org>
This commit is contained in:
Vijayavardhan Vennapusa 2016-04-12 16:03:33 +05:30 committed by Chandana Kishori Chiluveru
parent 58c91d96b2
commit 280fe6dcf1

View file

@ -624,11 +624,34 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep,
int ret = 0, size;
bool superspeed;
/*
* We must obtain the lock of the dwc3 core driver,
* including disabling interrupts, so we will be sure
* that we are the only ones that configure the HW device
* core and ensure that we queuing the request will finish
* as soon as possible so we will release back the lock.
*/
spin_lock_irqsave(&dwc->lock, flags);
if (!dep->endpoint.desc) {
dev_err(mdwc->dev,
"%s: trying to queue request %p to disabled ep %s\n",
__func__, request, ep->name);
spin_unlock_irqrestore(&dwc->lock, flags);
return -EPERM;
}
if (!request) {
dev_err(mdwc->dev, "%s: request is NULL\n", __func__);
spin_unlock_irqrestore(&dwc->lock, flags);
return -EINVAL;
}
if (!(request->udc_priv & MSM_SPS_MODE)) {
/* Not SPS mode, call original queue */
dev_vdbg(mdwc->dev, "%s: not sps mode, use regular queue\n",
__func__);
spin_unlock_irqrestore(&dwc->lock, flags);
return (mdwc->original_ep_ops[dep->number])->queue(ep,
request,
gfp_flags);
@ -637,9 +660,29 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep,
/* HW restriction regarding TRB size (8KB) */
if (req->request.length < 0x2000) {
dev_err(mdwc->dev, "%s: Min TRB size is 8KB\n", __func__);
spin_unlock_irqrestore(&dwc->lock, flags);
return -EINVAL;
}
if (dep->number == 0 || dep->number == 1) {
dev_err(mdwc->dev,
"%s: trying to queue dbm request %p to control ep %s\n",
__func__, request, ep->name);
spin_unlock_irqrestore(&dwc->lock, flags);
return -EPERM;
}
if (dep->busy_slot != dep->free_slot || !list_empty(&dep->request_list)
|| !list_empty(&dep->req_queued)) {
dev_err(mdwc->dev,
"%s: trying to queue dbm request %p tp ep %s\n",
__func__, request, ep->name);
spin_unlock_irqrestore(&dwc->lock, flags);
return -EPERM;
}
dep->busy_slot = 0;
dep->free_slot = 0;
/*
* Override req->complete function, but before doing that,
* store it's original pointer in the req_complete_list.
@ -647,6 +690,7 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep,
req_complete = kzalloc(sizeof(*req_complete), gfp_flags);
if (!req_complete) {
dev_err(mdwc->dev, "%s: not enough memory\n", __func__);
spin_unlock_irqrestore(&dwc->lock, flags);
return -ENOMEM;
}
req_complete->req = request;
@ -662,43 +706,6 @@ static int dwc3_msm_ep_queue(struct usb_ep *ep,
dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRHI(0)),
DWC3_GEVNTSIZ_SIZE(size));
/*
* We must obtain the lock of the dwc3 core driver,
* including disabling interrupts, so we will be sure
* that we are the only ones that configure the HW device
* core and ensure that we queuing the request will finish
* as soon as possible so we will release back the lock.
*/
spin_lock_irqsave(&dwc->lock, flags);
if (!dep->endpoint.desc) {
dev_err(mdwc->dev,
"%s: trying to queue request %p to disabled ep %s\n",
__func__, request, ep->name);
ret = -EPERM;
goto err;
}
if (dep->number == 0 || dep->number == 1) {
dev_err(mdwc->dev,
"%s: trying to queue dbm request %p to control ep %s\n",
__func__, request, ep->name);
ret = -EPERM;
goto err;
}
if (dep->busy_slot != dep->free_slot || !list_empty(&dep->request_list)
|| !list_empty(&dep->req_queued)) {
dev_err(mdwc->dev,
"%s: trying to queue dbm request %p tp ep %s\n",
__func__, request, ep->name);
ret = -EPERM;
goto err;
} else {
dep->busy_slot = 0;
dep->free_slot = 0;
}
ret = __dwc3_msm_ep_queue(dep, req);
if (ret < 0) {
dev_err(mdwc->dev,