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

Commit c290a210 authored by Devdutt Patnaik's avatar Devdutt Patnaik Committed by Hemant Kumar
Browse files

usb: gadget: f_gsi: Support power management using usb auto PM APIs



PM runtime APIs are used by function driver to synchronize between
controller low power mode and function driver specific tasks which
require controller to be active in order to finish them.

Change-Id: Ic9552d89c7eaeec53847364f05006ca72eb92f3a
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
Signed-off-by: default avatarDevdutt Patnaik <dpatnaik@codeaurora.org>
parent f937641b
Loading
Loading
Loading
Loading
+41 −2
Original line number Diff line number Diff line
@@ -627,8 +627,10 @@ static int ipa_suspend_work_handler(struct gsi_data_port *d_port)
	struct f_gsi *gsi = d_port_to_gsi(d_port);

	if (!usb_gsi_ep_op(gsi->d_port.in_ep, NULL,
				GSI_EP_OP_CHECK_FOR_SUSPEND))
				GSI_EP_OP_CHECK_FOR_SUSPEND)) {
		ret = -EFAULT;
		goto done;
	}

	ret = ipa_usb_xdci_suspend(gsi->d_port.out_channel_handle,
				gsi->d_port.in_channel_handle, gsi->prot_id);
@@ -677,6 +679,7 @@ static void ipa_work_handler(struct work_struct *w)
	struct gsi_data_port *d_port = container_of(w, struct gsi_data_port,
						  usb_ipa_w);
	u8 event;
	int ret = 0;

	event = read_event(d_port);

@@ -711,13 +714,17 @@ static void ipa_work_handler(struct work_struct *w)
				read_event(d_port);
				ipa_disconnect_work_handler(d_port);
				d_port->sm_state = STATE_INITIALIZED;
				usb_gadget_autopm_put_async(d_port->gadget);
				pr_debug("%s: STATE DISCONNECTED", __func__);
				break;
			}
			ipa_suspend_work_handler(d_port);
			ret = ipa_suspend_work_handler(d_port);
			if (!ret)
				usb_gadget_autopm_put_async(d_port->gadget);
		} else if (event == EVT_DISCONNECTED) {
			ipa_disconnect_work_handler(d_port);
			d_port->sm_state = STATE_INITIALIZED;
			usb_gadget_autopm_put_async(d_port->gadget);
			pr_debug("%s: STATE DISCONNECTED", __func__);
		}
		break;
@@ -725,15 +732,21 @@ static void ipa_work_handler(struct work_struct *w)
		if (event == EVT_DISCONNECTED) {
			ipa_disconnect_work_handler(d_port);
			d_port->sm_state = STATE_INITIALIZED;
			usb_gadget_autopm_put_async(d_port->gadget);

			pr_debug("%s: STATE DISCONNECTED", __func__);
		} else if (event == EVT_SUSPEND) {
			if (peek_event(d_port) == EVT_DISCONNECTED) {
				ipa_disconnect_work_handler(d_port);
				d_port->sm_state = STATE_INITIALIZED;
				usb_gadget_autopm_put_async(d_port->gadget);

				pr_debug("%s: STATE DISCONNECTED", __func__);
				break;
			}
			ipa_suspend_work_handler(d_port);
			if (!ret)
				usb_gadget_autopm_put_async(d_port->gadget);
		} else if (event == EVT_CONNECTED) {
			d_port->sm_state = STATE_CONNECTED;
			pr_debug("%s: DATA PATH CONNECTED", __func__);
@@ -752,13 +765,22 @@ static void ipa_work_handler(struct work_struct *w)
	case STATE_SUSPEND_IN_PROGRESS:
		if (event == EVT_IPA_SUSPEND) {
			d_port->sm_state = STATE_SUSPENDED;
			usb_gadget_autopm_put_async(d_port->gadget);
		} else	if (event == EVT_RESUMED) {
			ipa_resume_work_handler(d_port);
			d_port->sm_state = STATE_CONNECTED;
			/*
			 * Increment usage count here to disallow gadget
			 * parent suspend. This counter will decrement
			 * after IPA disconnect is done in disconnect work
			 * (due to cable disconnect) or in suspended state.
			 */
			usb_gadget_autopm_get_noresume(d_port->gadget);
			pr_debug("%s: STATE CONNECTED", __func__);
		} else if (event == EVT_DISCONNECTED) {
			ipa_disconnect_work_handler(d_port);
			d_port->sm_state = STATE_INITIALIZED;
			usb_gadget_autopm_put_async(d_port->gadget);
			pr_debug("%s: STATE DISCONNECTED", __func__);
		}
		break;
@@ -767,6 +789,14 @@ static void ipa_work_handler(struct work_struct *w)
		if (event == EVT_RESUMED) {
			ipa_resume_work_handler(d_port);
			d_port->sm_state = STATE_CONNECTED;
			/*
			 * Increment usage count here to disallow gadget
			 * parent suspend. This counter will decrement
			 * after IPA handshake is done in disconnect work
			 * (due to cable disconnect) or in suspended state.
			 */
			usb_gadget_autopm_get_noresume(d_port->gadget);

			pr_debug("%s: STATE CONNECTED", __func__);
		} else if (event == EVT_DISCONNECTED) {
			ipa_disconnect_work_handler(d_port);
@@ -1916,6 +1946,8 @@ static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
						GSI_EP_OP_CONFIG);
			}

			gsi->d_port.gadget = cdev->gadget;

			if (gsi->prot_id == IPA_USB_RNDIS) {
				gsi_rndis_open(gsi);
				net = gsi_rndis_get_netdev("rndis0");
@@ -1931,6 +1963,13 @@ static int gsi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
			if (gsi->prot_id == IPA_USB_ECM)
				gsi->d_port.cdc_filter = DEFAULT_FILTER;

			/*
			 * Increment usage count upon cable connect. Decrement
			 * after IPA disconnect is done in disconnect work
			 * (due to cable disconnect) or in suspend work.
			 */
			usb_gadget_autopm_get_noresume(gsi->d_port.gadget);

			post_event(&gsi->d_port, EVT_CONNECT_IN_PROGRESS);
			queue_work(gsi->d_port.ipa_usb_wq,
					&gsi->d_port.usb_ipa_w);
+1 −0
Original line number Diff line number Diff line
@@ -161,6 +161,7 @@ struct gsi_data_port {
	struct usb_ep *out_ep;
	struct usb_gsi_request in_request;
	struct usb_gsi_request out_request;
	struct usb_gadget *gadget;
	int (*ipa_usb_notify_cb)(enum ipa_usb_notify_event, void *driver_data);
	struct ipa_usb_teth_params ipa_init_params;
	int in_channel_handle;