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

Commit 29a95af9 authored by Jack Pham's avatar Jack Pham
Browse files

usb: dwc3-msm: Call pm_runtime_get/put on the parent device



Currently in start_peripheral() / start_host() the pm_runtime
get_sync() and put_sync() operations are being performed on the
dwc device. Since it is the mdwc parent device which actually
implements the callbacks to manage clocks and other resources,
it is more correct to ensure that the parent is not in suspend
to avoid any unclocked accesses.

Also replace the awkward one second delay in the A_HOST state
with proper PM autosuspend. This requires mark_last_busy() to be
called in start_host().

Change-Id: Ia8ae158f9ec7e4c91546f889892560df4b722735
Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
parent 2f43649b
Loading
Loading
Loading
Loading
+24 −28
Original line number Diff line number Diff line
@@ -2142,6 +2142,8 @@ static void dwc3_ext_event_notify(struct dwc3_msm *mdwc)

	if (!mdwc->init) {
		mdwc->init = true;
		pm_runtime_set_autosuspend_delay(mdwc->dev, 1000);
		pm_runtime_use_autosuspend(mdwc->dev);
		if (!work_busy(&mdwc->sm_work.work))
			schedule_delayed_work(&mdwc->sm_work, 0);

@@ -2150,6 +2152,7 @@ static void dwc3_ext_event_notify(struct dwc3_msm *mdwc)
		return;
	}


	schedule_delayed_work(&mdwc->sm_work, 0);
}

@@ -3078,17 +3081,17 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)
	if (on) {
		dev_dbg(mdwc->dev, "%s: turn on host\n", __func__);

		pm_runtime_get_sync(dwc->dev);
		pm_runtime_get_sync(mdwc->dev);
		dbg_event(0xFF, "StrtHost gync",
			atomic_read(&dwc->dev->power.usage_count));
			atomic_read(&mdwc->dev->power.usage_count));
		usb_phy_notify_connect(mdwc->hs_phy, USB_SPEED_HIGH);
		if (!IS_ERR(mdwc->vbus_reg))
			ret = regulator_enable(mdwc->vbus_reg);
		if (ret) {
			dev_err(dwc->dev, "unable to enable vbus_reg\n");
			pm_runtime_put_sync(dwc->dev);
			dev_err(mdwc->dev, "unable to enable vbus_reg\n");
			pm_runtime_put_sync(mdwc->dev);
			dbg_event(0xFF, "vregerr psync",
				atomic_read(&dwc->dev->power.usage_count));
				atomic_read(&mdwc->dev->power.usage_count));
			return ret;
		}

@@ -3109,9 +3112,9 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)
				__func__, ret);
			if (!IS_ERR(mdwc->vbus_reg))
				regulator_disable(mdwc->vbus_reg);
			pm_runtime_put_sync(dwc->dev);
			pm_runtime_put_sync(mdwc->dev);
			dbg_event(0xFF, "pdeverr psync",
				atomic_read(&dwc->dev->power.usage_count));
				atomic_read(&mdwc->dev->power.usage_count));
			return ret;
		}

@@ -3127,22 +3130,23 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)
		dwc3_gadget_usb3_phy_suspend(dwc, true);

		/* xHCI should have incremented child count as necessary */
		pm_runtime_put_sync(dwc->dev);
		dbg_event(0xFF, "StrtHost psync",
			atomic_read(&dwc->dev->power.usage_count));
			atomic_read(&mdwc->dev->power.usage_count));
		pm_runtime_mark_last_busy(mdwc->dev);
		pm_runtime_put_sync_autosuspend(mdwc->dev);
	} else {
		dev_dbg(dwc->dev, "%s: turn off host\n", __func__);
		dev_dbg(mdwc->dev, "%s: turn off host\n", __func__);

		if (!IS_ERR(mdwc->vbus_reg))
			ret = regulator_disable(mdwc->vbus_reg);
		if (ret) {
			dev_err(dwc->dev, "unable to disable vbus_reg\n");
			dev_err(mdwc->dev, "unable to disable vbus_reg\n");
			return ret;
		}

		pm_runtime_get_sync(dwc->dev);
		pm_runtime_get_sync(mdwc->dev);
		dbg_event(0xFF, "StopHost gsync",
			atomic_read(&dwc->dev->power.usage_count));
			atomic_read(&mdwc->dev->power.usage_count));
		usb_phy_notify_disconnect(mdwc->hs_phy, USB_SPEED_HIGH);
		platform_device_del(dwc->xhci);

@@ -3160,9 +3164,10 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)

		/* re-init core and OTG registers as block reset clears these */
		dwc3_post_host_reset_core_init(dwc);
		pm_runtime_put_sync(dwc->dev);
		pm_runtime_mark_last_busy(mdwc->dev);
		pm_runtime_put_sync_autosuspend(mdwc->dev);
		dbg_event(0xFF, "StopHost psync",
			atomic_read(&dwc->dev->power.usage_count));
			atomic_read(&mdwc->dev->power.usage_count));
	}

	return 0;
@@ -3180,9 +3185,9 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on)
{
	struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);

	pm_runtime_get_sync(dwc->dev);
	pm_runtime_get_sync(mdwc->dev);
	dbg_event(0xFF, "StrtGdgt gsync",
		atomic_read(&dwc->dev->power.usage_count));
		atomic_read(&mdwc->dev->power.usage_count));

	if (on) {
		dev_dbg(mdwc->dev, "%s: turn on gadget %s\n",
@@ -3206,9 +3211,9 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on)
		dwc3_gadget_usb3_phy_suspend(dwc, false);
	}

	pm_runtime_put_sync(dwc->dev);
	pm_runtime_put_sync(mdwc->dev);
	dbg_event(0xFF, "StopGdgt psync",
		atomic_read(&dwc->dev->power.usage_count));
		atomic_read(&mdwc->dev->power.usage_count));

	return 0;
}
@@ -3587,15 +3592,6 @@ static void dwc3_otg_sm_work(struct work_struct *w)
				dev_err(mdwc->dev, "unable to start host\n");
				mdwc->otg_state = OTG_STATE_A_IDLE;
				goto ret;
			} else {
				/*
				 * delay 1s to allow for xHCI to detect
				 * just-attached devices before allowing
				 * runtime suspend
				 */
				dev_dbg(mdwc->dev, "a_host state entered\n");
				delay = VBUS_REG_CHECK_DELAY;
				work = 1;
			}
		}
		break;