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

Commit 6e2175f8 authored by Manu Gautam's avatar Manu Gautam
Browse files

usb: f_gsi: Initiate remote-wakeup if notification already queued



Selective suspend of device (with remote-wakeup enabled) by host
could race with device driver queuing a notification request on
interrupt endpoint. Driver currently issues remote wakeup if at
the time of queueing notification request device was suspended.
If host suspends device right after driver queues notification
request then device driver fails to initiate remote-wakeup.
Fix this by initiating remote wakeup immediately after suspend
if notification request already queued to controller.

Change-Id: I24ce5d8302a70a1f5f68c54af0fef9f145adb97b
Signed-off-by: default avatarManu Gautam <mgautam@codeaurora.org>
parent 102b2cf1
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -2583,6 +2583,9 @@ static void gsi_disable(struct usb_function *f)

	atomic_set(&gsi->connected, 0);

	del_timer(&gsi->gsi_rw_timer);
	gsi->debugfs_rw_timer_enable = 0;

	if (gsi->prot_id == IPA_USB_RNDIS)
		rndis_uninit(gsi->config);

@@ -2633,6 +2636,15 @@ static void gsi_suspend(struct usb_function *f)
	post_event(&gsi->d_port, EVT_SUSPEND);
	queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w);
	log_event_dbg("gsi suspended");

	/* If host suspended bus without receiving notification request then
	 * initiate remote-wakeup. As driver won't be able to do it later since
	 * notification request is already queued.
	 */
	if (gsi->c_port.notify_req_queued && usb_gsi_remote_wakeup_allowed(f)) {
		mod_timer(&gsi->gsi_rw_timer, jiffies + msecs_to_jiffies(2000));
		log_event_dbg("%s: pending response, arm rw_timer\n", __func__);
	}
}

static void gsi_resume(struct usb_function *f)
@@ -2655,6 +2667,10 @@ static void gsi_resume(struct usb_function *f)
		f->func_is_suspended)
		return;

	/* Keep timer enabled if user enabled using debugfs */
	if (!gsi->debugfs_rw_timer_enable)
		del_timer(&gsi->gsi_rw_timer);

	if (gsi->c_port.notify && !gsi->c_port.notify->desc)
		config_ep_by_speed(cdev->gadget, f, gsi->c_port.notify);