Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7269ac10 authored by Jack Pham's avatar Jack Pham
Browse files

usb: dwc3-msm: Ignore multiple VBUS notifications



VBUS notifications arrive externally. There is a possibility that
they can arrive spuriously with the same value, which can cause
the resume_work function to get queued multiple times back-to-back.
This can result in the runtime PM counters getting out of sync,
For instance in the case of cable plug-in, if resume_work is called
multiple times, pm_runtime_get() is called multiply resulting in
runaway usage_counter increase. Upon cable disconnect, there would
be a mismatch in the number of times pm_runtime_put() is called
which leaves the device in a non-suspended state.

Prevent this by queuing the work function only when VBUS state
changes. Also add additional checking to the PHY_RESUME handling
such that pm_runtime_get() is not called if the usage counter is
already non-zero.

Change-Id: Ie7ac27c32e81f3c149ad7f2a64d8c8ebd0073617
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent 5a0974cf
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -2301,6 +2301,9 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy,
		dev_dbg(mdwc->dev, "%s: notify xceiv event\n", __func__);
		if (mdwc->otg_xceiv && !mdwc->ext_inuse &&
		    (mdwc->ext_xceiv.otg_capability || !init)) {
			if (mdwc->ext_xceiv.bsv == val->intval)
				break;

			mdwc->ext_xceiv.bsv = val->intval;
			/*
			 * Set debouncing delay to 120ms. Otherwise battery
+17 −13
Original line number Diff line number Diff line
@@ -364,8 +364,9 @@ static void dwc3_ext_event_notify(struct usb_otg *otg,
		flush_delayed_work(&dotg->sm_work);

	if (event == DWC3_EVENT_PHY_RESUME) {
		if (!pm_runtime_status_suspended(phy->dev))
			dev_warn(phy->dev, "PHY_RESUME event out of LPM!!!!\n");
		if (pm_runtime_status_suspended(phy->dev) ||
			atomic_read(&phy->dev->power.usage_count) == 0) {

			dev_dbg(phy->dev, "ext PHY_RESUME event received\n");
			/* ext_xceiver would have taken h/w out of LPM by now */
			ret = pm_runtime_get(phy->dev);
@@ -379,6 +380,9 @@ static void dwc3_ext_event_notify(struct usb_otg *otg,
			} else if (ret < 0) {
				dev_warn(phy->dev, "pm_runtime_get failed!\n");
			}
		} else {
			dev_warn(phy->dev, "PHY_RESUME event out of LPM!!!!\n");
		}
	} else if (event == DWC3_EVENT_XCEIV_STATE) {
		if (pm_runtime_status_suspended(phy->dev) ||
			atomic_read(&phy->dev->power.usage_count) == 0) {