usb: gadget: Don't giveback request if ep command times out
Currently driver is giving back requests to gadget even if the active transfers are not stopped. This might lead the controller to access the requests which are already unmapped. This change adds a judgement for giving back the requests to gadget based on ep command status. Also if ep command times out and the controller doesn't stop correctly then mark it as an error event and restart the USB session. Change-Id: If32cddddf0544140d5bdf68df9144702e00dc758 Signed-off-by: Pratham Pratap <prathampratap@codeaurora.org>
This commit is contained in:
parent
66d2f99836
commit
d8ed6a031f
2 changed files with 21 additions and 8 deletions
|
@ -904,7 +904,12 @@ static void dwc3_stop_active_transfers_to_halt(struct dwc3 *dwc)
|
|||
if (!(dep->flags & DWC3_EP_ENABLED))
|
||||
continue;
|
||||
|
||||
dwc3_stop_active_transfer_noioc(dwc, dep->number, true);
|
||||
/*
|
||||
* If the transfers didn't stop due to some reason
|
||||
* don't giveback the request to gadget driver.
|
||||
*/
|
||||
if (dwc3_stop_active_transfer_noioc(dwc, dep->number, true))
|
||||
continue;
|
||||
|
||||
/* - giveback all requests to gadget driver */
|
||||
while (!list_empty(&dep->started_list)) {
|
||||
|
@ -2327,7 +2332,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
|
|||
dwc->softconnect = is_on;
|
||||
|
||||
if ((dwc3_is_otg_or_drd(dwc) && !dwc->vbus_active)
|
||||
|| !dwc->gadget_driver) {
|
||||
|| !dwc->gadget_driver || dwc->err_evt_seen) {
|
||||
/*
|
||||
* Need to wait for vbus_session(on) from otg driver or to
|
||||
* the udc_start.
|
||||
|
@ -2391,8 +2396,15 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
|
|||
ret = dwc3_gadget_run_stop_util(dwc);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
if (!is_on && ret == -ETIMEDOUT) {
|
||||
dev_err(dwc->dev, "%s: Core soft reset...\n", __func__);
|
||||
dwc3_device_core_soft_reset(dwc);
|
||||
/*
|
||||
* If we fail to stop the controller then mark it as an error
|
||||
* event since it can lead the controller to go into an unknown
|
||||
* state.
|
||||
*/
|
||||
dbg_log_string("%s: error event seen\n", __func__);
|
||||
dwc->err_evt_seen = true;
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_ERROR_EVENT, 0);
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_CLEAR_DB, 0);
|
||||
}
|
||||
enable_irq(dwc->irq);
|
||||
|
||||
|
@ -3295,17 +3307,17 @@ void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force)
|
|||
dep->name, dep->number, ret);
|
||||
}
|
||||
|
||||
void dwc3_stop_active_transfer_noioc(struct dwc3 *dwc, u32 epnum, bool force)
|
||||
int dwc3_stop_active_transfer_noioc(struct dwc3 *dwc, u32 epnum, bool force)
|
||||
{
|
||||
struct dwc3_ep *dep;
|
||||
struct dwc3_gadget_ep_cmd_params params;
|
||||
u32 cmd;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
dep = dwc->eps[epnum];
|
||||
|
||||
if (!dep->resource_index)
|
||||
return;
|
||||
return ret;
|
||||
|
||||
if (dep->endpoint.endless)
|
||||
dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER,
|
||||
|
@ -3321,6 +3333,7 @@ void dwc3_stop_active_transfer_noioc(struct dwc3 *dwc, u32 epnum, bool force)
|
|||
|
||||
dbg_log_string("%s(%d): endxfer ret:%d)",
|
||||
dep->name, dep->number, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
|
||||
|
|
|
@ -126,7 +126,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
|
|||
gfp_t gfp_flags);
|
||||
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
|
||||
void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force);
|
||||
void dwc3_stop_active_transfer_noioc(struct dwc3 *dwc, u32 epnum, bool force);
|
||||
int dwc3_stop_active_transfer_noioc(struct dwc3 *dwc, u32 epnum, bool force);
|
||||
void dwc3_ep_inc_enq(struct dwc3_ep *dep);
|
||||
void dwc3_ep_inc_deq(struct dwc3_ep *dep);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue