aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVirupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>2013-04-24 02:38:48 -0400
committerFelipe Balbi <balbi@ti.com>2013-05-28 15:17:21 -0400
commited74df12dc3e07a37d99aab60211496e871488a0 (patch)
treea3120bee76e30698158ece47090e16efc37ad236
parent5bf8fae33d14cc5c3c53a926f9079f92c8b082b0 (diff)
usb: musb: make use_sg flag URB specific
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. Cc: stable <stable@vger.kernel.org> # 3.7+ Acked-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com> Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/musb/musb_host.c18
-rw-r--r--drivers/usb/musb/musb_host.h1
2 files changed, 9 insertions, 10 deletions
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 8914dec49f01..9d3044bdebe5 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -1232,7 +1232,6 @@ void musb_host_tx(struct musb *musb, u8 epnum)
1232 void __iomem *mbase = musb->mregs; 1232 void __iomem *mbase = musb->mregs;
1233 struct dma_channel *dma; 1233 struct dma_channel *dma;
1234 bool transfer_pending = false; 1234 bool transfer_pending = false;
1235 static bool use_sg;
1236 1235
1237 musb_ep_select(mbase, epnum); 1236 musb_ep_select(mbase, epnum);
1238 tx_csr = musb_readw(epio, MUSB_TXCSR); 1237 tx_csr = musb_readw(epio, MUSB_TXCSR);
@@ -1463,9 +1462,9 @@ done:
1463 * NULL. 1462 * NULL.
1464 */ 1463 */
1465 if (!urb->transfer_buffer) 1464 if (!urb->transfer_buffer)
1466 use_sg = true; 1465 qh->use_sg = true;
1467 1466
1468 if (use_sg) { 1467 if (qh->use_sg) {
1469 /* sg_miter_start is already done in musb_ep_program */ 1468 /* sg_miter_start is already done in musb_ep_program */
1470 if (!sg_miter_next(&qh->sg_miter)) { 1469 if (!sg_miter_next(&qh->sg_miter)) {
1471 dev_err(musb->controller, "error: sg list empty\n"); 1470 dev_err(musb->controller, "error: sg list empty\n");
@@ -1484,9 +1483,9 @@ done:
1484 1483
1485 qh->segsize = length; 1484 qh->segsize = length;
1486 1485
1487 if (use_sg) { 1486 if (qh->use_sg) {
1488 if (offset + length >= urb->transfer_buffer_length) 1487 if (offset + length >= urb->transfer_buffer_length)
1489 use_sg = false; 1488 qh->use_sg = false;
1490 } 1489 }
1491 1490
1492 musb_ep_select(mbase, epnum); 1491 musb_ep_select(mbase, epnum);
@@ -1552,7 +1551,6 @@ void musb_host_rx(struct musb *musb, u8 epnum)
1552 bool done = false; 1551 bool done = false;
1553 u32 status; 1552 u32 status;
1554 struct dma_channel *dma; 1553 struct dma_channel *dma;
1555 static bool use_sg;
1556 unsigned int sg_flags = SG_MITER_ATOMIC | SG_MITER_TO_SG; 1554 unsigned int sg_flags = SG_MITER_ATOMIC | SG_MITER_TO_SG;
1557 1555
1558 musb_ep_select(mbase, epnum); 1556 musb_ep_select(mbase, epnum);
@@ -1878,12 +1876,12 @@ void musb_host_rx(struct musb *musb, u8 epnum)
1878 * NULL. 1876 * NULL.
1879 */ 1877 */
1880 if (!urb->transfer_buffer) { 1878 if (!urb->transfer_buffer) {
1881 use_sg = true; 1879 qh->use_sg = true;
1882 sg_miter_start(&qh->sg_miter, urb->sg, 1, 1880 sg_miter_start(&qh->sg_miter, urb->sg, 1,
1883 sg_flags); 1881 sg_flags);
1884 } 1882 }
1885 1883
1886 if (use_sg) { 1884 if (qh->use_sg) {
1887 if (!sg_miter_next(&qh->sg_miter)) { 1885 if (!sg_miter_next(&qh->sg_miter)) {
1888 dev_err(musb->controller, "error: sg list empty\n"); 1886 dev_err(musb->controller, "error: sg list empty\n");
1889 sg_miter_stop(&qh->sg_miter); 1887 sg_miter_stop(&qh->sg_miter);
@@ -1913,8 +1911,8 @@ finish:
1913 urb->actual_length += xfer_len; 1911 urb->actual_length += xfer_len;
1914 qh->offset += xfer_len; 1912 qh->offset += xfer_len;
1915 if (done) { 1913 if (done) {
1916 if (use_sg) 1914 if (qh->use_sg)
1917 use_sg = false; 1915 qh->use_sg = false;
1918 1916
1919 if (urb->status == -EINPROGRESS) 1917 if (urb->status == -EINPROGRESS)
1920 urb->status = status; 1918 urb->status = status;
diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h
index 5a9c8feec10c..738f7eb60df9 100644
--- a/drivers/usb/musb/musb_host.h
+++ b/drivers/usb/musb/musb_host.h
@@ -74,6 +74,7 @@ struct musb_qh {
74 u16 frame; /* for periodic schedule */ 74 u16 frame; /* for periodic schedule */
75 unsigned iso_idx; /* in urb->iso_frame_desc[] */ 75 unsigned iso_idx; /* in urb->iso_frame_desc[] */
76 struct sg_mapping_iter sg_miter; /* for highmem in PIO mode */ 76 struct sg_mapping_iter sg_miter; /* for highmem in PIO mode */
77 bool use_sg; /* to track urb using sglist */
77}; 78};
78 79
79/* map from control or bulk queue head to the first qh on that ring */ 80/* map from control or bulk queue head to the first qh on that ring */