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

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
...@@ -1232,7 +1232,6 @@ void musb_host_tx(struct musb *musb, u8 epnum) ...@@ -1232,7 +1232,6 @@ void musb_host_tx(struct musb *musb, u8 epnum)
void __iomem *mbase = musb->mregs; void __iomem *mbase = musb->mregs;
struct dma_channel *dma; struct dma_channel *dma;
bool transfer_pending = false; bool transfer_pending = false;
static bool use_sg;
musb_ep_select(mbase, epnum); musb_ep_select(mbase, epnum);
tx_csr = musb_readw(epio, MUSB_TXCSR); tx_csr = musb_readw(epio, MUSB_TXCSR);
...@@ -1463,9 +1462,9 @@ void musb_host_tx(struct musb *musb, u8 epnum) ...@@ -1463,9 +1462,9 @@ void musb_host_tx(struct musb *musb, u8 epnum)
* NULL. * NULL.
*/ */
if (!urb->transfer_buffer) 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 */ /* sg_miter_start is already done in musb_ep_program */
if (!sg_miter_next(&qh->sg_miter)) { if (!sg_miter_next(&qh->sg_miter)) {
dev_err(musb->controller, "error: sg list empty\n"); dev_err(musb->controller, "error: sg list empty\n");
...@@ -1484,9 +1483,9 @@ void musb_host_tx(struct musb *musb, u8 epnum) ...@@ -1484,9 +1483,9 @@ void musb_host_tx(struct musb *musb, u8 epnum)
qh->segsize = length; qh->segsize = length;
if (use_sg) { if (qh->use_sg) {
if (offset + length >= urb->transfer_buffer_length) if (offset + length >= urb->transfer_buffer_length)
use_sg = false; qh->use_sg = false;
} }
musb_ep_select(mbase, epnum); musb_ep_select(mbase, epnum);
...@@ -1552,7 +1551,6 @@ void musb_host_rx(struct musb *musb, u8 epnum) ...@@ -1552,7 +1551,6 @@ void musb_host_rx(struct musb *musb, u8 epnum)
bool done = false; bool done = false;
u32 status; u32 status;
struct dma_channel *dma; struct dma_channel *dma;
static bool use_sg;
unsigned int sg_flags = SG_MITER_ATOMIC | SG_MITER_TO_SG; unsigned int sg_flags = SG_MITER_ATOMIC | SG_MITER_TO_SG;
musb_ep_select(mbase, epnum); musb_ep_select(mbase, epnum);
...@@ -1878,12 +1876,12 @@ void musb_host_rx(struct musb *musb, u8 epnum) ...@@ -1878,12 +1876,12 @@ void musb_host_rx(struct musb *musb, u8 epnum)
* NULL. * NULL.
*/ */
if (!urb->transfer_buffer) { if (!urb->transfer_buffer) {
use_sg = true; qh->use_sg = true;
sg_miter_start(&qh->sg_miter, urb->sg, 1, sg_miter_start(&qh->sg_miter, urb->sg, 1,
sg_flags); sg_flags);
} }
if (use_sg) { if (qh->use_sg) {
if (!sg_miter_next(&qh->sg_miter)) { if (!sg_miter_next(&qh->sg_miter)) {
dev_err(musb->controller, "error: sg list empty\n"); dev_err(musb->controller, "error: sg list empty\n");
sg_miter_stop(&qh->sg_miter); sg_miter_stop(&qh->sg_miter);
...@@ -1913,8 +1911,8 @@ void musb_host_rx(struct musb *musb, u8 epnum) ...@@ -1913,8 +1911,8 @@ void musb_host_rx(struct musb *musb, u8 epnum)
urb->actual_length += xfer_len; urb->actual_length += xfer_len;
qh->offset += xfer_len; qh->offset += xfer_len;
if (done) { if (done) {
if (use_sg) if (qh->use_sg)
use_sg = false; qh->use_sg = false;
if (urb->status == -EINPROGRESS) if (urb->status == -EINPROGRESS)
urb->status = status; urb->status = status;
......
...@@ -74,6 +74,7 @@ struct musb_qh { ...@@ -74,6 +74,7 @@ struct musb_qh {
u16 frame; /* for periodic schedule */ u16 frame; /* for periodic schedule */
unsigned iso_idx; /* in urb->iso_frame_desc[] */ unsigned iso_idx; /* in urb->iso_frame_desc[] */
struct sg_mapping_iter sg_miter; /* for highmem in PIO mode */ 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 */ /* map from control or bulk queue head to the first qh on that ring */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment