[PATCH 14/84] usb: musb: make use_sg flag URB specific

From: Kamal Mostafa
Date: Mon Jun 17 2013 - 14:00:05 EST


3.8.13.3 -stable review patch. If anyone has any objections, please let me know.

------------------

From: Virupax Sadashivpetimath <virupax.sadashivpetimath@xxxxxxxxxxxxxx>

commit ed74df12dc3e07a37d99aab60211496e871488a0 upstream.

Since highmem PIO URB handling was introduced in:

8e8a551 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.

Acked-by: Linus Walleij <linus.walleij@xxxxxxxxxx>
Signed-off-by: Virupax Sadashivpetimath <virupax.sadashivpetimath@xxxxxxxxxxxxxx>
Signed-off-by: Fabio Baltieri <fabio.baltieri@xxxxxxxxxx>
Signed-off-by: Felipe Balbi <balbi@xxxxxx>
Signed-off-by: Kamal Mostafa <kamal@xxxxxxxxxxxxx>
---
drivers/usb/musb/musb_host.c | 18 ++++++++----------
drivers/usb/musb/musb_host.h | 1 +
2 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index e9f0fd9..c131eb6 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -1212,7 +1212,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);
@@ -1443,9 +1442,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");
@@ -1464,9 +1463,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);
@@ -1532,7 +1531,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);
@@ -1858,12 +1856,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);
@@ -1893,8 +1891,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;
diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h
index 5a9c8fe..738f7eb 100644
--- a/drivers/usb/musb/musb_host.h
+++ b/drivers/usb/musb/musb_host.h
@@ -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 */
--
1.8.1.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/