usb: dwc3: Clear err_evt_seen flag on disconnect

Currently err_evt_seen flag is cleared only while clearing
run/stop. Consider a case where err_evt_seen flag is set and
controller is swtiching from peripheral mode to host mode.
Now, from dwc3_gadget_pullup driver will bail out since the
flag is set. Also since softconnect flag is not set run_stop
will not get cleared from vbus_session(0), leaving the err
evt_seen flag set. If any interrupt is generated then driver
will bail out from interrupt handler without processing the
interrupt, which can lead to irq storm. Fix this by clearing
the err_evt_seen flag in disconnect and also add a judgement
in pullup so that driver can proceed with clearing run/stop
if softconnect is cleared, even with the err_evt_seen flag is
set.

Change-Id: Ib7026dca8b4e76e943832419b19cef180ca96171
Signed-off-by: Pratham Pratap <prathampratap@codeaurora.org>
This commit is contained in:
Pratham Pratap 2021-01-21 23:05:58 +05:30
commit 9bbf449b96
2 changed files with 8 additions and 2 deletions

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/module.h>
@ -4992,6 +4992,11 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on)
mdwc->in_device_mode = false;
usb_gadget_vbus_disconnect(&dwc->gadget);
/*
* Clearing err_evt_seen after disconnect ensures that interrupts
* are ignored if err_evt_seen is set
*/
dwc->err_evt_seen = false;
usb_phy_notify_disconnect(mdwc->hs_phy, USB_SPEED_HIGH);
usb_phy_notify_disconnect(mdwc->ss_phy, USB_SPEED_SUPER);
redriver_notify_disconnect(mdwc->ss_redriver_node);

View file

@ -2330,7 +2330,8 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
dwc->softconnect = is_on;
if (((dwc->dr_mode > USB_DR_MODE_HOST) && !dwc->vbus_active)
|| !dwc->gadget_driver || dwc->err_evt_seen) {
|| !dwc->gadget_driver || (dwc->err_evt_seen &&
dwc->softconnect)) {
/*
* Need to wait for vbus_session(on) from otg driver or to
* the udc_start.