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

Commit 049f7f17 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "dwc3-msm: Fix dwc3_drd_state_string for undefined state"

parents 6b712e99 eb8e5395
Loading
Loading
Loading
Loading
+81 −35
Original line number Diff line number Diff line
@@ -135,6 +135,34 @@ struct dwc3_msm_req_complete {
			      struct usb_request *req);
};

enum dwc3_drd_state {
	DRD_STATE_UNDEFINED = 0,

	DRD_STATE_IDLE,
	DRD_STATE_PERIPHERAL,
	DRD_STATE_PERIPHERAL_SUSPEND,

	DRD_STATE_HOST_IDLE,
	DRD_STATE_HOST,
};

static const char *const state_names[] = {
	[DRD_STATE_UNDEFINED] = "undefined",
	[DRD_STATE_IDLE] = "idle",
	[DRD_STATE_PERIPHERAL] = "peripheral",
	[DRD_STATE_PERIPHERAL_SUSPEND] = "peripheral_suspend",
	[DRD_STATE_HOST_IDLE] = "host_idle",
	[DRD_STATE_HOST] = "host",
};

static const char *dwc3_drd_state_string(enum dwc3_drd_state state)
{
	if (state < 0 || state >= ARRAY_SIZE(state_names))
		return "UNKNOWN";

	return state_names[state];
}

enum dwc3_id_state {
	DWC3_ID_GROUND = 0,
	DWC3_ID_FLOAT,
@@ -175,6 +203,7 @@ static const struct usb_irq usb_irq_info[USB_MAX_IRQ] = {
#define ID			0
#define B_SESS_VLD		1
#define B_SUSPEND		2
#define WAIT_FOR_LPM		3

#define PM_QOS_SAMPLE_SEC	2
#define PM_QOS_THRESHOLD	400
@@ -220,7 +249,7 @@ struct dwc3_msm {
	unsigned long		inputs;
	unsigned int		max_power;
	bool			charging_disabled;
	enum usb_otg_state	otg_state;
	enum dwc3_drd_state	drd_state;
	u32			bus_perf_client;
	struct msm_bus_scale_pdata	*bus_scale_table;
	struct power_supply	*usb_psy;
@@ -2110,7 +2139,7 @@ static void dwc3_msm_power_collapse_por(struct dwc3_msm *mdwc)
	dwc3_msm_write_reg_field(mdwc->base, PWR_EVNT_IRQ_MASK_REG,
				PWR_EVNT_POWERDOWN_IN_P3_MASK, 1);

	if (mdwc->otg_state == OTG_STATE_A_HOST) {
	if (mdwc->drd_state == DRD_STATE_HOST) {
		dev_dbg(mdwc->dev, "%s: set the core in host mode\n",
							__func__);
		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
@@ -2298,7 +2327,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool hibernation)
	}

	if (!mdwc->vbus_active && dwc->is_drd &&
		mdwc->otg_state == OTG_STATE_B_PERIPHERAL) {
		mdwc->drd_state == DRD_STATE_PERIPHERAL) {
		/*
		 * In some cases, the pm_runtime_suspend may be called by
		 * usb_bam when there is pending lpm flag. However, if this is
@@ -2320,7 +2349,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool hibernation)
	 * then check controller state of L2 and break
	 * LPM sequence. Check this for device bus suspend case.
	 */
	if ((dwc->is_drd && mdwc->otg_state == OTG_STATE_B_SUSPEND) &&
	if ((dwc->is_drd && mdwc->drd_state == DRD_STATE_PERIPHERAL_SUSPEND) &&
		(dwc->gadget.state != USB_STATE_CONFIGURED)) {
		pr_err("%s(): Trying to go in LPM with state:%d\n",
					__func__, dwc->gadget.state);
@@ -2335,8 +2364,8 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool hibernation)
	 */

	if (!mdwc->in_host_mode && (mdwc->vbus_active &&
		(mdwc->otg_state == OTG_STATE_B_SUSPEND ||
		mdwc->otg_state == OTG_STATE_B_PERIPHERAL) && !mdwc->suspend)) {
		(mdwc->drd_state == DRD_STATE_PERIPHERAL_SUSPEND ||
		mdwc->drd_state == DRD_STATE_PERIPHERAL) && !mdwc->suspend)) {
		dev_dbg(mdwc->dev,
			"Received wakeup event before the core suspend\n");
		mutex_unlock(&mdwc->suspend_resume_mutex);
@@ -2463,7 +2492,13 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc, bool hibernation)

	dev_info(mdwc->dev, "DWC3 in low power mode\n");
	dbg_event(0xFF, "Ctl Sus", atomic_read(&dwc->in_lpm));

	/* kick_sm if it is waiting for lpm sequence to finish */
	if (test_and_clear_bit(WAIT_FOR_LPM, &mdwc->inputs))
		schedule_delayed_work(&mdwc->sm_work, 0);

	mutex_unlock(&mdwc->suspend_resume_mutex);

	return 0;
}

@@ -4105,6 +4140,9 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)
		dwc3_usb3_phy_suspend(dwc, false);
		mdwc->in_host_mode = false;

		/* wait for LPM, to ensure h/w is reset after stop_host */
		set_bit(WAIT_FOR_LPM, &mdwc->inputs);

		pm_runtime_put_sync_suspend(mdwc->dev);
		dbg_event(0xFF, "StopHost psync",
			atomic_read(&mdwc->dev->power.usage_count));
@@ -4188,6 +4226,9 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on)
		usb_phy_notify_disconnect(mdwc->ss_phy, USB_SPEED_SUPER);
		dwc3_override_vbus_status(mdwc, false);
		dwc3_usb3_phy_suspend(dwc, false);

		/* wait for LPM, to ensure h/w is reset after stop_peripheral */
		set_bit(WAIT_FOR_LPM, &mdwc->inputs);
	}

	pm_runtime_put_sync(mdwc->dev);
@@ -4240,7 +4281,7 @@ static int dwc3_restart_usb_host_mode(struct notifier_block *nb,
	dbg_event(0xFF, "pm_runtime_sus", ret);

	dwc->maximum_speed = usb_speed;
	mdwc->otg_state = OTG_STATE_B_IDLE;
	mdwc->drd_state = DRD_STATE_IDLE;
	schedule_delayed_work(&mdwc->sm_work, 0);
	dbg_event(0xFF, "complete_host_change", dwc->maximum_speed);
err:
@@ -4307,7 +4348,7 @@ static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned int mA)
 *
 * @w: Pointer to the dwc3 otg workqueue
 *
 * NOTE: After any change in otg_state, we must reschdule the state machine.
 * NOTE: After any change in drd_state, we must reschdule the state machine.
 */
static void dwc3_otg_sm_work(struct work_struct *w)
{
@@ -4326,13 +4367,13 @@ static void dwc3_otg_sm_work(struct work_struct *w)
		return;
	}

	state = usb_otg_state_string(mdwc->otg_state);
	state = dwc3_drd_state_string(mdwc->drd_state);
	dev_dbg(mdwc->dev, "%s state\n", state);
	dbg_event(0xFF, state, 0);

	/* Check OTG state */
	switch (mdwc->otg_state) {
	case OTG_STATE_UNDEFINED:
	switch (mdwc->drd_state) {
	case DRD_STATE_UNDEFINED:
		/* put controller and phy in suspend if no cable connected */
		if (test_bit(ID, &mdwc->inputs) &&
				!test_bit(B_SESS_VLD, &mdwc->inputs)) {
@@ -4344,19 +4385,24 @@ static void dwc3_otg_sm_work(struct work_struct *w)
			pm_runtime_put_sync(mdwc->dev);
			dbg_event(0xFF, "Undef NoUSB",
				atomic_read(&mdwc->dev->power.usage_count));
			mdwc->otg_state = OTG_STATE_B_IDLE;
			mdwc->drd_state = DRD_STATE_IDLE;
			break;
		}

		dbg_event(0xFF, "Exit UNDEF", 0);
		mdwc->otg_state = OTG_STATE_B_IDLE;
		mdwc->drd_state = DRD_STATE_IDLE;
		pm_runtime_set_suspended(mdwc->dev);
		pm_runtime_enable(mdwc->dev);
		/* fall-through */
	case OTG_STATE_B_IDLE:
	case DRD_STATE_IDLE:
		if (test_bit(WAIT_FOR_LPM, &mdwc->inputs)) {
			dev_dbg(mdwc->dev, "still not in lpm, wait.\n");
			break;
		}

		if (!test_bit(ID, &mdwc->inputs)) {
			dev_dbg(mdwc->dev, "!id\n");
			mdwc->otg_state = OTG_STATE_A_IDLE;
			mdwc->drd_state = DRD_STATE_HOST_IDLE;
			work = 1;
		} else if (test_bit(B_SESS_VLD, &mdwc->inputs)) {
			dev_dbg(mdwc->dev, "b_sess_vld\n");
@@ -4366,14 +4412,14 @@ static void dwc3_otg_sm_work(struct work_struct *w)
				msecs_to_jiffies(SDP_CONNETION_CHECK_TIME));
			/*
			 * Increment pm usage count upon cable connect. Count
			 * is decremented in OTG_STATE_B_PERIPHERAL state on
			 * is decremented in DRD_STATE_PERIPHERAL state on
			 * cable disconnect or in bus suspend.
			 */
			pm_runtime_get_sync(mdwc->dev);
			dbg_event(0xFF, "BIDLE gsync",
				atomic_read(&mdwc->dev->power.usage_count));
			dwc3_otg_start_peripheral(mdwc, 1);
			mdwc->otg_state = OTG_STATE_B_PERIPHERAL;
			mdwc->drd_state = DRD_STATE_PERIPHERAL;
			work = 1;
		} else {
			dwc3_msm_gadget_vbus_draw(mdwc, 0);
@@ -4381,17 +4427,17 @@ static void dwc3_otg_sm_work(struct work_struct *w)
		}
		break;

	case OTG_STATE_B_PERIPHERAL:
	case DRD_STATE_PERIPHERAL:
		if (!test_bit(B_SESS_VLD, &mdwc->inputs) ||
				!test_bit(ID, &mdwc->inputs)) {
			dev_dbg(mdwc->dev, "!id || !bsv\n");
			mdwc->otg_state = OTG_STATE_B_IDLE;
			mdwc->drd_state = DRD_STATE_IDLE;
			cancel_delayed_work_sync(&mdwc->sdp_check);
			dwc3_otg_start_peripheral(mdwc, 0);
			/*
			 * Decrement pm usage count upon cable disconnect
			 * which was incremented upon cable connect in
			 * OTG_STATE_B_IDLE state
			 * DRD_STATE_IDLE state
			 */
			pm_runtime_put_sync_suspend(mdwc->dev);
			dbg_event(0xFF, "!BSV psync",
@@ -4400,13 +4446,13 @@ static void dwc3_otg_sm_work(struct work_struct *w)
		} else if (test_bit(B_SUSPEND, &mdwc->inputs) &&
			test_bit(B_SESS_VLD, &mdwc->inputs)) {
			dev_dbg(mdwc->dev, "BPER bsv && susp\n");
			mdwc->otg_state = OTG_STATE_B_SUSPEND;
			mdwc->drd_state = DRD_STATE_PERIPHERAL_SUSPEND;
			/*
			 * Decrement pm usage count upon bus suspend.
			 * Count was incremented either upon cable
			 * connect in OTG_STATE_B_IDLE or host
			 * connect in DRD_STATE_IDLE or host
			 * initiated resume after bus suspend in
			 * OTG_STATE_B_SUSPEND state
			 * DRD_STATE_PERIPHERAL_SUSPEND state
			 */
			pm_runtime_mark_last_busy(mdwc->dev);
			pm_runtime_put_autosuspend(mdwc->dev);
@@ -4415,20 +4461,20 @@ static void dwc3_otg_sm_work(struct work_struct *w)
		}
		break;

	case OTG_STATE_B_SUSPEND:
	case DRD_STATE_PERIPHERAL_SUSPEND:
		if (!test_bit(B_SESS_VLD, &mdwc->inputs)) {
			dev_dbg(mdwc->dev, "BSUSP: !bsv\n");
			mdwc->otg_state = OTG_STATE_B_IDLE;
			mdwc->drd_state = DRD_STATE_IDLE;
			cancel_delayed_work_sync(&mdwc->sdp_check);
			dwc3_otg_start_peripheral(mdwc, 0);
		} else if (!test_bit(B_SUSPEND, &mdwc->inputs)) {
			dev_dbg(mdwc->dev, "BSUSP !susp\n");
			mdwc->otg_state = OTG_STATE_B_PERIPHERAL;
			mdwc->drd_state = DRD_STATE_PERIPHERAL;
			/*
			 * Increment pm usage count upon host
			 * initiated resume. Count was decremented
			 * upon bus suspend in
			 * OTG_STATE_B_PERIPHERAL state.
			 * DRD_STATE_PERIPHERAL state.
			 */
			pm_runtime_get_sync(mdwc->dev);
			dbg_event(0xFF, "!SUSP gsync",
@@ -4436,15 +4482,15 @@ static void dwc3_otg_sm_work(struct work_struct *w)
		}
		break;

	case OTG_STATE_A_IDLE:
	case DRD_STATE_HOST_IDLE:
		/* Switch to A-Device*/
		if (test_bit(ID, &mdwc->inputs)) {
			dev_dbg(mdwc->dev, "id\n");
			mdwc->otg_state = OTG_STATE_B_IDLE;
			mdwc->drd_state = DRD_STATE_IDLE;
			mdwc->vbus_retry_count = 0;
			work = 1;
		} else {
			mdwc->otg_state = OTG_STATE_A_HOST;
			mdwc->drd_state = DRD_STATE_HOST;
			ret = dwc3_otg_start_host(mdwc, 1);
			if ((ret == -EPROBE_DEFER) &&
						mdwc->vbus_retry_count < 3) {
@@ -4452,24 +4498,24 @@ static void dwc3_otg_sm_work(struct work_struct *w)
				 * Get regulator failed as regulator driver is
				 * not up yet. Will try to start host after 1sec
				 */
				mdwc->otg_state = OTG_STATE_A_IDLE;
				mdwc->drd_state = DRD_STATE_HOST_IDLE;
				dev_dbg(mdwc->dev, "Unable to get vbus regulator. Retrying...\n");
				delay = VBUS_REG_CHECK_DELAY;
				work = 1;
				mdwc->vbus_retry_count++;
			} else if (ret) {
				dev_err(mdwc->dev, "unable to start host\n");
				mdwc->otg_state = OTG_STATE_A_IDLE;
				mdwc->drd_state = DRD_STATE_HOST_IDLE;
				goto ret;
			}
		}
		break;

	case OTG_STATE_A_HOST:
	case DRD_STATE_HOST:
		if (test_bit(ID, &mdwc->inputs) || mdwc->hc_died) {
			dev_dbg(mdwc->dev, "id || hc_died\n");
			dwc3_otg_start_host(mdwc, 0);
			mdwc->otg_state = OTG_STATE_B_IDLE;
			mdwc->drd_state = DRD_STATE_IDLE;
			mdwc->vbus_retry_count = 0;
			mdwc->hc_died = false;
			work = 1;
@@ -4582,7 +4628,7 @@ static int dwc3_msm_pm_restore(struct device *dev)
	pm_runtime_enable(dev);

	/* Restore PHY flags if hibernated in host mode */
	if (mdwc->otg_state == OTG_STATE_A_HOST) {
	if (mdwc->drd_state == DRD_STATE_HOST) {
		usb_phy_notify_connect(mdwc->hs_phy, USB_SPEED_HIGH);
		mdwc->hs_phy->flags |= PHY_HOST_MODE;
		if (mdwc->ss_phy) {