usb: dwc3: gadget: Check controller status with endpoint enable/disable

Some USB function driver (e.g. mass storage) performs USB endpoint enable
and disable functionality from worker thread context instead of composite/
controller work context. This may result into endpoint enable/disable
racing against USB controller low power mode functionality with USB cable
disconnect. This race may result into unclock register access. Hence fix
this issue by checking USB controller status and perform resume/autosuspend
with endpoint disable whereas return -EINVAL with endpoint enable if USB
controller is suspended (in low power mode).

Change-Id: I76cd75fc90b52ceefe099f48be6c880c04136301
Signed-off-by: Mayank Rana <mrana@codeaurora.org>
This commit is contained in:
Mayank Rana 2020-07-23 12:17:30 -07:00
commit ad8d260c33

View file

@ -914,6 +914,12 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
dep->name))
return 0;
if (pm_runtime_suspended(dwc->sysdev)) {
dev_err(dwc->dev, "fail ep_enable %s device is into LPM\n",
dep->name);
return -EINVAL;
}
spin_lock_irqsave(&dwc->lock, flags);
ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_INIT);
dbg_event(dep->number, "ENABLE", ret);
@ -942,10 +948,13 @@ static int dwc3_gadget_ep_disable(struct usb_ep *ep)
dep->name))
return 0;
pm_runtime_get_sync(dwc->dev);
spin_lock_irqsave(&dwc->lock, flags);
ret = __dwc3_gadget_ep_disable(dep);
dbg_event(dep->number, "DISABLE", ret);
spin_unlock_irqrestore(&dwc->lock, flags);
pm_runtime_mark_last_busy(dwc->dev);
pm_runtime_put_sync_autosuspend(dwc->dev);
return ret;
}