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

Commit f2f3da25 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: dwc3: Ensure blocking_sync waits until host mode starts or stops"

parents a74f80d6 7bb30153
Loading
Loading
Loading
Loading
+21 −29
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@
#include "xhci.h"

#define SDP_CONNETION_CHECK_TIME 10000 /* in ms */
#define EXTCON_SYNC_EVENT_TIMEOUT_MS 1500 /* in ms */

/* time out to wait for USB cable status notification (in ms)*/
#define SM_INIT_TIMEOUT 30000
@@ -4454,47 +4455,40 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on)
	return 0;
}

/**
 * dwc3_usb_blocking_sync - Waits until event is completed or maximum upto 1.5
 * secs.
 *
 * @host_enable_event: Event can be start usb host or stop usb host.
 */
static int dwc3_usb_blocking_sync(struct notifier_block *nb,
				unsigned long event, void *ptr)
				unsigned long host_enable_event, void *ptr)
{
	struct dwc3 *dwc;
	struct extcon_dev *edev = ptr;
	struct extcon_nb *enb = container_of(nb, struct extcon_nb,
						blocking_sync_nb);
	struct dwc3_msm *mdwc = enb->mdwc;
	int ret = 0;
	unsigned long timeout_ms = jiffies +
			msecs_to_jiffies(EXTCON_SYNC_EVENT_TIMEOUT_MS);

	if (!edev || !mdwc)
		return NOTIFY_DONE;

	dwc = platform_get_drvdata(mdwc->dwc3);

	dbg_event(0xFF, "fw_blocksync", 0);
	flush_work(&mdwc->resume_work);
	drain_workqueue(mdwc->sm_usb_wq);

	if (!mdwc->in_host_mode && !mdwc->in_device_mode) {
		dbg_event(0xFF, "lpm_state", atomic_read(&dwc->in_lpm));
	do {
		if (mdwc->drd_state == (host_enable_event ? DRD_STATE_HOST
					: DRD_STATE_IDLE))
			break;
		msleep(50);
	} while (time_before(jiffies, timeout_ms));

		/*
		 * stop host mode functionality performs autosuspend with mdwc
		 * device, and it may take sometime to call PM runtime suspend.
		 * Hence call pm_runtime_suspend() API to invoke PM runtime
		 * suspend immediately to put USB controller and PHYs into
		 * suspend.
		 */
		ret = pm_runtime_suspend(mdwc->dev);
		dbg_event(0xFF, "pm_runtime_sus", ret);
	if (!time_before(jiffies, timeout_ms))
		dev_err(mdwc->dev, "TIMEOUT when changing the state\n");

		/*
		 * If mdwc device is already suspended, pm_runtime_suspend() API
		 * returns 1, which is not error. Overwrite with zero if it is.
		 */
		if (ret > 0)
			ret = 0;
	}

	return ret;
	return 0;
}

static int get_psy_type(struct dwc3_msm *mdwc)
@@ -4714,8 +4708,6 @@ static void dwc3_otg_sm_work(struct work_struct *w)
			mdwc->vbus_retry_count = 0;
			work = 1;
		} else {
			mdwc->drd_state = DRD_STATE_HOST;

			ret = dwc3_otg_start_host(mdwc, 1);
			if ((ret == -EPROBE_DEFER) &&
						mdwc->vbus_retry_count < 3) {
@@ -4723,15 +4715,15 @@ 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->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->drd_state = DRD_STATE_HOST_IDLE;
				goto ret;
			} else {
				mdwc->drd_state = DRD_STATE_HOST;
			}
		}
		break;
+8 −3
Original line number Diff line number Diff line
@@ -347,6 +347,10 @@ static void *usbpd_ipc_log;
#define ID_HDR_PRODUCT_AMA	5
#define ID_HDR_PRODUCT_VPD	6

/* params for usb_blocking_sync */
#define STOP_USB_HOST		0
#define START_USB_HOST		1

#define PD_MIN_SINK_CURRENT	900

static const u32 default_src_caps[] = { 0x36019096 };	/* VSafe5V @ 1.5A */
@@ -553,7 +557,7 @@ static inline void start_usb_host(struct usbpd *pd, bool ss)
	extcon_set_state_sync(pd->extcon, EXTCON_USB_HOST, 1);

	/* blocks until USB host is completely started */
	ret = extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST, 1);
	ret = extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST, START_USB_HOST);
	if (ret) {
		usbpd_err(&pd->dev, "err(%d) starting host", ret);
		return;
@@ -637,7 +641,7 @@ static int usbpd_release_ss_lane(struct usbpd *pd,
	stop_usb_host(pd);

	/* blocks until USB host is completely stopped */
	ret = extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST, 0);
	ret = extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST, STOP_USB_HOST);
	if (ret) {
		usbpd_err(&pd->dev, "err(%d) stopping host", ret);
		goto err_exit;
@@ -1907,7 +1911,8 @@ static void dr_swap(struct usbpd *pd)
		typec_set_data_role(pd->typec_port, TYPEC_HOST);

		/* ensure host is started before allowing DP */
		extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST, 0);
		extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST,
					START_USB_HOST);

		usbpd_send_svdm(pd, USBPD_SID, USBPD_SVDM_DISCOVER_IDENTITY,
				SVDM_CMD_TYPE_INITIATOR, 0, NULL, 0);