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

Commit 702aaf46 authored by Manu Gautam's avatar Manu Gautam
Browse files

USB: ci13xxx_udc: Avoid unclocked access if pm_runtime_get fails



If remote wakeup request is received during system resume where
resume_early is still processing, pm_runtime_get_sync returns
-EACCES error as runtime_pm for a device is disabled between
late_suspend and early_resume.
This results in runtime_get_sync failing to bring hardware out
of low power mode state followed by unclocked access of registers
as part of remote wakeup.

Fix this by retrying runtime_resume if pm_runtime_get_sync fails
with -EACCESS.

Change-Id: I73c0d0da57e40392d00793a5b3814dd04105ef63
Signed-off-by: default avatarManu Gautam <mgautam@codeaurora.org>
parent fab1b6d5
Loading
Loading
Loading
Loading
+24 −1
Original line number Diff line number Diff line
@@ -1613,11 +1613,14 @@ done:
}
static DEVICE_ATTR(dtds, S_IWUSR, NULL, print_dtds);

#define CI_PM_RESUME_RETRIES	5    /* Max Number of retries */

static int ci13xxx_wakeup(struct usb_gadget *_gadget)
{
	struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
	unsigned long flags;
	int ret = 0;
	static int retry_count;

	trace();

@@ -1629,7 +1632,27 @@ static int ci13xxx_wakeup(struct usb_gadget *_gadget)
	}
	spin_unlock_irqrestore(udc->lock, flags);

	pm_runtime_get_sync(&_gadget->dev);
	ret = pm_runtime_get_sync(&_gadget->dev);
	if (ret) {
		/* pm_runtime_get_sync returns -EACCES error between
		 * late_suspend and early_resume, wait for system resume to
		 * finish and perform resume from work_queue again
		 */
		pr_debug("PM runtime get sync failed, ret %d\n", ret);
		if (ret == -EACCES) {
			pm_runtime_put_noidle(&_gadget->dev);
			if (retry_count == CI_PM_RESUME_RETRIES) {
				pr_err("pm_runtime_get_sync timed out\n");
				retry_count = 0;
				return 0;
			}
			retry_count++;
			schedule_delayed_work(&udc->rw_work,
					      REMOTE_WAKEUP_DELAY);
			return 0;
		}
	}
	retry_count = 0;

	udc->udc_driver->notify_event(udc,
		CI13XXX_CONTROLLER_REMOTE_WAKEUP_EVENT);