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

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

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

parents 684b1834 c290a210
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -743,6 +743,7 @@ struct dwc3_scratchpad_array {
#define DWC3_CONTROLLER_CONNDONE_EVENT			8
#define DWC3_CONTROLLER_NOTIFY_OTG_EVENT		9
#define DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT		10
#define DWC3_CONTROLLER_RESTART_USB_SESSION		11

#define MAX_INTR_STATS					10
/**
+10 −2
Original line number Diff line number Diff line
@@ -1437,7 +1437,7 @@ static void dwc3_restart_usb_work(struct work_struct *w)
	dev_dbg(mdwc->dev, "%s\n", __func__);

	if (atomic_read(&dwc->in_lpm) || !dwc->is_drd) {
		dev_err(mdwc->dev, "%s failed!!!\n", __func__);
		dev_dbg(mdwc->dev, "%s failed!!!\n", __func__);
		return;
	}

@@ -1462,7 +1462,10 @@ static void dwc3_restart_usb_work(struct work_struct *w)
		msleep(20);

	if (!timeout) {
		dev_warn(mdwc->dev, "Not in LPM after disconnect, forcing suspend...\n");
		dev_dbg(mdwc->dev,
			"Not in LPM after disconnect, forcing suspend...\n");
		dbg_event(0xFF, "ReStart:RT SUSP",
			atomic_read(&mdwc->dev->power.usage_count));
		pm_runtime_suspend(mdwc->dev);
	}

@@ -1474,6 +1477,7 @@ static void dwc3_restart_usb_work(struct work_struct *w)
	}

	dwc->err_evt_seen = false;
	flush_delayed_work(&mdwc->sm_work);
}

/**
@@ -1743,6 +1747,10 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event)
		dev_dbg(mdwc->dev, "DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT received\n");
		dwc3_msm_gadget_vbus_draw(mdwc, dwc->vbus_draw);
		break;
	case DWC3_CONTROLLER_RESTART_USB_SESSION:
		dev_dbg(mdwc->dev, "DWC3_CONTROLLER_RESTART_USB_SESSION received\n");
		dwc3_restart_usb_work(&mdwc->restart_usb_work);
		break;
	default:
		dev_dbg(mdwc->dev, "unknown dwc3 event\n");
		break;
+8 −0
Original line number Diff line number Diff line
@@ -2226,6 +2226,13 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
	return 0;
}

static int dwc3_gadget_restart_usb_session(struct usb_gadget *g)
{
	struct dwc3		*dwc = gadget_to_dwc(g);

	return dwc3_notify_event(dwc, DWC3_CONTROLLER_RESTART_USB_SESSION);
}

static const struct usb_gadget_ops dwc3_gadget_ops = {
	.get_frame		= dwc3_gadget_get_frame,
	.wakeup			= dwc3_gadget_wakeup,
@@ -2236,6 +2243,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
	.pullup			= dwc3_gadget_pullup,
	.udc_start		= dwc3_gadget_start,
	.udc_stop		= dwc3_gadget_stop,
	.restart		= dwc3_gadget_restart_usb_session,
};

/* -------------------------------------------------------------------------- */
+48 −2
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ MODULE_PARM_DESC(num_out_bufs,
		"Number of OUT buffers");

static struct workqueue_struct *ipa_usb_wq;
static bool gadget_restarted;

struct usb_gsi_debugfs {
	struct dentry *debugfs_root;
@@ -626,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);
@@ -676,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);

@@ -710,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;
@@ -724,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__);
@@ -751,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;
@@ -766,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);
@@ -1915,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");
@@ -1930,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);
@@ -2591,6 +2631,7 @@ static void gsi_unbind(struct usb_configuration *c, struct usb_function *f)
	 */
	flush_workqueue(gsi->d_port.ipa_usb_wq);
	ipa_usb_deinit_teth_prot(gsi->prot_id);
	gadget_restarted = false;

	if (gsi->prot_id == IPA_USB_RNDIS) {
		gsi->d_port.sm_state = STATE_UNINITIALIZED;
@@ -2643,6 +2684,11 @@ int gsi_bind_config(struct usb_configuration *c, enum ipa_usb_teth_prot prot_id)
		return -EINVAL;
	}

	if (!gadget_restarted) {
		usb_gadget_restart(c->cdev->gadget);
		gadget_restarted = true;
	}

	switch (prot_id) {
	case IPA_USB_RNDIS:
		gsi->function.name = "rndis";
+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;
Loading