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:
parent
58c91d96b2
commit
280fe6dcf1
1 changed files with 44 additions and 37 deletions
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue