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

Commit df86e172 authored by Manu Gautam's avatar Manu Gautam
Browse files

usb: u_bam_data: Reset DBM only if USB request was dequeued



When using USB DBM for Bam2Bam mode, if usb_req is dequeued
as part of bus suspend then corresponding DBM EP should also
be reset along with USB BAM and IPA pipe resets.
USB BAM driver takes care of resetting BAM pipes at the end
of suspend routine after USB_CONS is released. But, in case
where USB BUS is resumed before usb_bam could finish suspend
there is a possbility that usb_bam doesn't dequeued the IN
usb_req and it doesn't reset pipes as well. But, u_bam_data
driver unaware of this still resets DBM EP on resume which
results in DATA stall. Fix this by adding a check to perform
DBM reset only if usb_request was dequeued. This would ensure
that as part of following usb_bam_resume pipes would also be
reset.

CRs-fixed: 779200
Change-Id: I78ff8feac27883fb53705025785113708863bbd2
Signed-off-by: default avatarManu Gautam <mgautam@codeaurora.org>
parent 073af1cb
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1217,7 +1217,7 @@ static void reset_pipe_for_resume(struct usb_bam_pipe_connect *pipe_connect)
		pr_err("%s failed to reset the IPA pipe\n", __func__);
		return;
	}

	pr_debug("%s: USB/IPA pipes reset after resume\n", __func__);
}

/* Stop PROD transfers in case they were started */
+13 −2
Original line number Diff line number Diff line
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -114,6 +114,7 @@ struct bam_data_ch_info {
	unsigned int		rx_flow_control_triggered;
	/* used for RNDIS/ECM network inteface based design */
	atomic_t		is_net_interface_up;
	bool			tx_req_dequeued;
};

static struct work_struct *rndis_conn_w;
@@ -652,6 +653,7 @@ static void bam_data_stop_endless_rx(struct bam_data_port *port)

	spin_unlock_irqrestore(&port->port_lock, flags);
}

static void bam_data_stop_endless_tx(struct bam_data_port *port)
{
	struct bam_data_ch_info *d = &port->data_ch;
@@ -665,6 +667,7 @@ static void bam_data_stop_endless_tx(struct bam_data_port *port)
		return;
	}
	ep = port->port_usb->in;
	d->tx_req_dequeued = true;
	spin_unlock_irqrestore(&port->port_lock, flags);

	pr_debug("%s: dequeue\n", __func__);
@@ -2000,8 +2003,15 @@ static void bam2bam_data_resume_work(struct work_struct *w)
	}

	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
		/*
		 * If usb_req was dequeued as part of bus suspend then
		 * corresponding DBM EP should also be reset.
		 * There is a possbility that usb_bam may not have dequeued the
		 * request in case of quick back to back usb bus suspend resume.
		 */
		if (gadget_is_dwc3(gadget) &&
			msm_dwc3_reset_ep_after_lpm(gadget)) {
			msm_dwc3_reset_ep_after_lpm(gadget) &&
					d->tx_req_dequeued) {
				configure_usb_data_fifo(d->src_bam_idx,
					port->port_usb->out,
					d->src_pipe_type);
@@ -2010,6 +2020,7 @@ static void bam2bam_data_resume_work(struct work_struct *w)
					d->dst_pipe_type);
				msm_dwc3_reset_dbm_ep(port->port_usb->in);
		}
		d->tx_req_dequeued = false;
		usb_bam_resume(&d->ipa_params);
	}
exit: