Patch fixes alauda not to use stack as URB transfer_buffer. URB buffers need to
be DMA-able, which stack is not.

Patch is only compile tested.

Cc: sta...@vger.kernel.org
Signed-off-by: Jussi Kivilinna <jussi.kivili...@iki.fi>
---
 drivers/mtd/nand/alauda.c |   74 ++++++++++++++++++++++++++++++++++-----------
 1 file changed, 56 insertions(+), 18 deletions(-)

diff --git a/drivers/mtd/nand/alauda.c b/drivers/mtd/nand/alauda.c
index 60a0dfd..e99e302 100644
--- a/drivers/mtd/nand/alauda.c
+++ b/drivers/mtd/nand/alauda.c
@@ -69,6 +69,9 @@ struct alauda {
        struct mtd_info         *mtd;
        struct alauda_card      *card;
        struct mutex            card_mutex;
+       void                    *card_cmdbuf;
+       void                    *card_oobbuf;
+       void                    *card_ignore_buf;
        u32                     pagemask;
        u32                     bytemask;
        u32                     blockmask;
@@ -119,6 +122,13 @@ static void alauda_delete(struct kref *kref)
 {
        struct alauda *al = container_of(kref, struct alauda, kref);
 
+       kfree(al[0].card_cmdbuf);
+       kfree(al[1].card_cmdbuf);
+       kfree(al[0].card_oobbuf);
+       kfree(al[1].card_oobbuf);
+       kfree(al[0].card_ignore_buf);
+       kfree(al[1].card_ignore_buf);
+
        if (al->mtd) {
                mtd_device_unregister(al->mtd);
                kfree(al->mtd);
@@ -133,7 +143,9 @@ static int alauda_get_media_status(struct alauda *al, void 
*buf)
 
        mutex_lock(&al->card_mutex);
        ret = usb_control_msg(al->dev, usb_rcvctrlpipe(al->dev, 0),
-                       ALAUDA_GET_XD_MEDIA_STATUS, 0xc0, 0, 1, buf, 2, HZ);
+                       ALAUDA_GET_XD_MEDIA_STATUS, 0xc0, 0, 1, al->card_cmdbuf,
+                       2, HZ);
+       memcpy(buf, al->card_cmdbuf, 2);
        mutex_unlock(&al->card_mutex);
        return ret;
 }
@@ -155,7 +167,9 @@ static int alauda_get_media_signatures(struct alauda *al, 
void *buf)
 
        mutex_lock(&al->card_mutex);
        ret = usb_control_msg(al->dev, usb_rcvctrlpipe(al->dev, 0),
-                       ALAUDA_GET_XD_MEDIA_SIG, 0xc0, 0, 0, buf, 4, HZ);
+                       ALAUDA_GET_XD_MEDIA_SIG, 0xc0, 0, 0, al->card_cmdbuf,
+                       4, HZ);
+       memcpy(buf, al->card_cmdbuf, 4);
        mutex_unlock(&al->card_mutex);
        return ret;
 }
@@ -167,7 +181,8 @@ static void alauda_reset(struct alauda *al)
                0, 0, 0, 0, al->port
        };
        mutex_lock(&al->card_mutex);
-       usb_bulk_msg(al->dev, al->bulk_out, command, 9, NULL, HZ);
+       memcpy(al->card_cmdbuf, command, 9);
+       usb_bulk_msg(al->dev, al->bulk_out, al->card_cmdbuf, 9, NULL, HZ);
        mutex_unlock(&al->card_mutex);
 }
 
@@ -223,14 +238,17 @@ static int __alauda_read_page(struct mtd_info *mtd, 
loff_t from, void *buf,
                        goto out;
        }
        init_completion(&sg.comp);
-       usb_fill_bulk_urb(sg.urb[0], al->dev, al->bulk_out, command, 9,
+
+       mutex_lock(&al->card_mutex);
+
+       memcpy(al->card_cmdbuf, command, 9);
+       usb_fill_bulk_urb(sg.urb[0], al->dev, al->bulk_out, al->card_cmdbuf, 9,
                        alauda_complete, NULL);
        usb_fill_bulk_urb(sg.urb[1], al->dev, al->bulk_in, buf, mtd->writesize,
                        alauda_complete, NULL);
-       usb_fill_bulk_urb(sg.urb[2], al->dev, al->bulk_in, oob, 16,
+       usb_fill_bulk_urb(sg.urb[2], al->dev, al->bulk_in, al->card_oobbuf, 16,
                        alauda_complete, &sg.comp);
 
-       mutex_lock(&al->card_mutex);
        for (i=0; i<3; i++) {
                err = usb_submit_urb(sg.urb[i], GFP_NOIO);
                if (err)
@@ -243,6 +261,7 @@ cancel:
                        usb_kill_urb(sg.urb[i]);
                }
        }
+       memcpy(oob, al->card_oobbuf, 16);
        mutex_unlock(&al->card_mutex);
 
 out:
@@ -288,14 +307,18 @@ static int alauda_write_page(struct mtd_info *mtd, loff_t 
to, void *buf,
                        goto out;
        }
        init_completion(&sg.comp);
-       usb_fill_bulk_urb(sg.urb[0], al->dev, al->bulk_out, command, 9,
-                       alauda_complete, NULL);
-       usb_fill_bulk_urb(sg.urb[1], al->dev, al->write_out, buf,mtd->writesize,
-                       alauda_complete, NULL);
-       usb_fill_bulk_urb(sg.urb[2], al->dev, al->write_out, oob, 16,
-                       alauda_complete, &sg.comp);
 
        mutex_lock(&al->card_mutex);
+
+       memcpy(al->card_cmdbuf, command, 9);
+       memcpy(al->card_oobbuf, oob, 16);
+       usb_fill_bulk_urb(sg.urb[0], al->dev, al->bulk_out, al->card_cmdbuf, 9,
+                       alauda_complete, NULL);
+       usb_fill_bulk_urb(sg.urb[1], al->dev, al->write_out, buf,
+                         mtd->writesize, alauda_complete, NULL);
+       usb_fill_bulk_urb(sg.urb[2], al->dev, al->write_out, al->card_oobbuf,
+                         16, alauda_complete, &sg.comp);
+
        for (i=0; i<3; i++) {
                err = usb_submit_urb(sg.urb[i], GFP_NOIO);
                if (err)
@@ -326,7 +349,6 @@ static int alauda_erase_block(struct mtd_info *mtd, loff_t 
ofs)
                ALAUDA_BULK_CMD, ALAUDA_BULK_ERASE_BLOCK, PBA_HI(pba),
                PBA_ZONE(pba), 0, PBA_LO(pba), 0x02, 0, al->port
        };
-       u8 buf[2];
        int i, err;
 
        for (i=0; i<2; i++)
@@ -339,12 +361,15 @@ static int alauda_erase_block(struct mtd_info *mtd, 
loff_t ofs)
                        goto out;
        }
        init_completion(&sg.comp);
-       usb_fill_bulk_urb(sg.urb[0], al->dev, al->bulk_out, command, 9,
+
+       mutex_lock(&al->card_mutex);
+
+       memcpy(al->card_cmdbuf, command, 9);
+       usb_fill_bulk_urb(sg.urb[0], al->dev, al->bulk_out, al->card_cmdbuf, 9,
                        alauda_complete, NULL);
-       usb_fill_bulk_urb(sg.urb[1], al->dev, al->bulk_in, buf, 2,
+       usb_fill_bulk_urb(sg.urb[1], al->dev, al->bulk_in, al->card_oobbuf, 2,
                        alauda_complete, &sg.comp);
 
-       mutex_lock(&al->card_mutex);
        for (i=0; i<2; i++) {
                err = usb_submit_urb(sg.urb[i], GFP_NOIO);
                if (err)
@@ -367,9 +392,9 @@ out:
 
 static int alauda_read_oob(struct mtd_info *mtd, loff_t from, void *oob)
 {
-       static u8 ignore_buf[512]; /* write only */
+       struct alauda *al = mtd->priv;
 
-       return __alauda_read_page(mtd, from, ignore_buf, oob);
+       return __alauda_read_page(mtd, from, al->card_ignore_buf, oob);
 }
 
 static int alauda_isbad(struct mtd_info *mtd, loff_t ofs)
@@ -677,6 +702,19 @@ static int alauda_probe(struct usb_interface *interface,
        /* second device is identical up to now */
        memcpy(al+1, al, sizeof(*al));
 
+       al[0].card_cmdbuf = kmalloc(9, GFP_KERNEL);
+       al[1].card_cmdbuf = kmalloc(9, GFP_KERNEL);
+       al[0].card_oobbuf = kmalloc(16, GFP_KERNEL);
+       al[1].card_oobbuf = kmalloc(16, GFP_KERNEL);
+       al[0].card_ignore_buf = kmalloc(512, GFP_KERNEL);
+       al[1].card_ignore_buf = kmalloc(512, GFP_KERNEL);
+       if (!al[0].card_cmdbuf || !al[1].card_cmdbuf || !al[0].card_oobbuf ||
+           !al[1].card_oobbuf || !al[0].card_ignore_buf ||
+           !al[1].card_ignore_buf) {
+               err = -ENOMEM;
+               goto error;
+       }
+
        mutex_init(&al[0].card_mutex);
        mutex_init(&al[1].card_mutex);
 

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to