[PATCH] alauda: do not use stack for URB transfer_buffers

Jussi Kivilinna jussi.kivilinna at iki.fi
Tue Aug 6 08:03:29 EDT 2013


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: stable at vger.kernel.org
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at 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);
 




More information about the linux-mtd mailing list