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

Commit 445d25b1 authored by Manu Gautam's avatar Manu Gautam
Browse files

usb: gadget: ECM: Check if data interface is UP while bus_suspend



CDC ECM requires DATA interface to support two alternate settings.
Bulk (IO) endpoints must be supported only in 1st alternate setting,
not in the default one. Alternate setting is chosen by host using
SET_INTERFACE command after SET_CONFIGURATION. SET_CONFIG results
in set_alt(0) followed by set_alt(1) when SET_INTERFACE is sent.
There is a possibility of USB bus getting suspended between this
window of SET_CONFIG and SET_INTERFACE. This currently results in
a crash in bus_suspend routine of ECM which assumes that by this
time DATA interface would be up. Fix this by adding a check in
ECM bus_suspend/resume routines to bail out if set_alt(1) is not
yet received by device.

CRs-fixed: 614120
Change-Id: Ic002b75f20d2d4f23f6a5dd7b4df365c25f20e0f
Signed-off-by: default avatarManu Gautam <mgautam@codeaurora.org>
parent 2a9f3229
Loading
Loading
Loading
Loading
+18 −0
Original line number Original line Diff line number Diff line
@@ -424,6 +424,12 @@ static int ecm_qc_bam_connect(struct f_ecm_qc *dev)
static int ecm_qc_bam_disconnect(struct f_ecm_qc *dev)
static int ecm_qc_bam_disconnect(struct f_ecm_qc *dev)
{
{
	pr_debug("%s: dev:%p. Disconnect BAM.\n", __func__, dev);
	pr_debug("%s: dev:%p. Disconnect BAM.\n", __func__, dev);

	dev->bam_port.cdev = NULL;
	dev->bam_port.func = NULL;
	dev->bam_port.in = NULL;
	dev->bam_port.out = NULL;

	bam_data_disconnect(&dev->bam_port, 0);
	bam_data_disconnect(&dev->bam_port, 0);


	return 0;
	return 0;
@@ -686,6 +692,12 @@ static void ecm_qc_suspend(struct usb_function *f)
{
{
	struct f_ecm_qc	*ecm = func_to_ecm_qc(f);
	struct f_ecm_qc	*ecm = func_to_ecm_qc(f);


	/* Is DATA interface initialized? */
	if (!ecm->bam_port.cdev) {
		pr_debug("data interface not up\n");
		return;
	}

	if (f->config->cdev->gadget->remote_wakeup) {
	if (f->config->cdev->gadget->remote_wakeup) {
		bam_data_suspend(ECM_QC_ACTIVE_PORT);
		bam_data_suspend(ECM_QC_ACTIVE_PORT);
	} else {
	} else {
@@ -708,6 +720,12 @@ static void ecm_qc_resume(struct usb_function *f)
{
{
	struct f_ecm_qc	*ecm = func_to_ecm_qc(f);
	struct f_ecm_qc	*ecm = func_to_ecm_qc(f);


	/* Nothing to do if DATA interface wasn't initialized */
	if (!ecm->bam_port.cdev) {
		pr_debug("data interface was not up\n");
		return;
	}

	if (f->config->cdev->gadget->remote_wakeup) {
	if (f->config->cdev->gadget->remote_wakeup) {
		bam_data_resume(ECM_QC_ACTIVE_PORT);
		bam_data_resume(ECM_QC_ACTIVE_PORT);
	} else {
	} else {