Commit ed74df12 authored by Virupax Sadashivpetimath's avatar Virupax Sadashivpetimath Committed by Felipe Balbi
Browse files

usb: musb: make use_sg flag URB specific



Since highmem PIO URB handling was introduced in:

8e8a5516 usb: musb: host: Handle highmem in PIO mode

when a URB is being handled it may happen that the static use_sg flag
was set by a previous URB with buffer in highmem.  This leads to error
in handling the present URB.

Fix this by making the use_sg flag URB specific.

Cc: stable <stable@vger.kernel.org> # 3.7+
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarVirupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>
Signed-off-by: default avatarFabio Baltieri <fabio.baltieri@linaro.org>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 5bf8fae3
Loading
Loading
Loading
Loading
+8 −10
Original line number Diff line number Diff line
@@ -1232,7 +1232,6 @@ void musb_host_tx(struct musb *musb, u8 epnum)
	void __iomem		*mbase = musb->mregs;
	struct dma_channel	*dma;
	bool			transfer_pending = false;
	static bool use_sg;

	musb_ep_select(mbase, epnum);
	tx_csr = musb_readw(epio, MUSB_TXCSR);
@@ -1463,9 +1462,9 @@ done:
	 * NULL.
	 */
	if (!urb->transfer_buffer)
		use_sg = true;
		qh->use_sg = true;

	if (use_sg) {
	if (qh->use_sg) {
		/* sg_miter_start is already done in musb_ep_program */
		if (!sg_miter_next(&qh->sg_miter)) {
			dev_err(musb->controller, "error: sg list empty\n");
@@ -1484,9 +1483,9 @@ done:

	qh->segsize = length;

	if (use_sg) {
	if (qh->use_sg) {
		if (offset + length >= urb->transfer_buffer_length)
			use_sg = false;
			qh->use_sg = false;
	}

	musb_ep_select(mbase, epnum);
@@ -1552,7 +1551,6 @@ void musb_host_rx(struct musb *musb, u8 epnum)
	bool			done = false;
	u32			status;
	struct dma_channel	*dma;
	static bool use_sg;
	unsigned int sg_flags = SG_MITER_ATOMIC | SG_MITER_TO_SG;

	musb_ep_select(mbase, epnum);
@@ -1878,12 +1876,12 @@ void musb_host_rx(struct musb *musb, u8 epnum)
			 * NULL.
			 */
			if (!urb->transfer_buffer) {
				use_sg = true;
				qh->use_sg = true;
				sg_miter_start(&qh->sg_miter, urb->sg, 1,
						sg_flags);
			}

			if (use_sg) {
			if (qh->use_sg) {
				if (!sg_miter_next(&qh->sg_miter)) {
					dev_err(musb->controller, "error: sg list empty\n");
					sg_miter_stop(&qh->sg_miter);
@@ -1913,8 +1911,8 @@ finish:
	urb->actual_length += xfer_len;
	qh->offset += xfer_len;
	if (done) {
		if (use_sg)
			use_sg = false;
		if (qh->use_sg)
			qh->use_sg = false;

		if (urb->status == -EINPROGRESS)
			urb->status = status;
+1 −0
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ struct musb_qh {
	u16			frame;		/* for periodic schedule */
	unsigned		iso_idx;	/* in urb->iso_frame_desc[] */
	struct sg_mapping_iter sg_miter;	/* for highmem in PIO mode */
	bool			use_sg;		/* to track urb using sglist */
};

/* map from control or bulk queue head to the first qh on that ring */