From patchwork Tue Aug 6 12:03:29 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jussi Kivilinna X-Patchwork-Id: 265043 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from casper.infradead.org (unknown [IPv6:2001:770:15f::2]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 8B9842C007B for ; Tue, 6 Aug 2013 22:04:11 +1000 (EST) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1V6fzh-0001uB-Ry; Tue, 06 Aug 2013 12:04:06 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1V6fzg-0003vJ-7K; Tue, 06 Aug 2013 12:04:04 +0000 Received: from sypressi.dnainternet.net ([83.102.40.135]) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1V6fzc-0003sp-PJ for linux-mtd@lists.infradead.org; Tue, 06 Aug 2013 12:04:02 +0000 Received: from localhost (localhost [127.0.0.1]) by sypressi.dnainternet.net (Postfix) with ESMTP id 4AB80260688; Tue, 6 Aug 2013 15:03:35 +0300 (EEST) X-Virus-Scanned: DNA Postiturva at dnainternet.net X-Spam-Flag: NO X-Spam-Score: -1 X-Spam-Level: X-Spam-Status: No, score=-1 tagged_above=-9999 required=6 tests=[ALL_TRUSTED=-1] autolearn=disabled Received: from sypressi.dnainternet.net ([83.102.40.135]) by localhost (sypressi.dnainternet.net [127.0.0.1]) (DNA Postiturva, port 10041) with ESMTP id mFTt5zkbeiFZ; Tue, 6 Aug 2013 15:03:34 +0300 (EEST) Received: from omenapuu.dnainternet.net (omenapuu.dnainternet.net [83.102.40.212]) by sypressi.dnainternet.net (Postfix) with ESMTP id 8DAB1260486; Tue, 6 Aug 2013 15:03:34 +0300 (EEST) Received: from hayate.dalek.fi (dyn2-212-50-133-197.psoas.suomi.net [212.50.133.197]) (using TLSv1.2 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by omenapuu.dnainternet.net (Postfix) with ESMTPS id 61CED5FA9C; Tue, 6 Aug 2013 15:03:30 +0300 (EEST) Received: from fate.lan ([10.0.0.10] helo=fate) by hayate.dalek.fi with esmtp (Exim 4.80) (envelope-from ) id 1V6fz7-0002xK-UX; Tue, 06 Aug 2013 15:03:29 +0300 Received: from localhost6.localdomain6 (unknown [127.0.0.1]) by fate (Postfix) with ESMTP id E28AF2007C9; Tue, 6 Aug 2013 15:03:29 +0300 (EEST) Subject: [PATCH] alauda: do not use stack for URB transfer_buffers To: linux-mtd@lists.infradead.org From: Jussi Kivilinna Date: Tue, 06 Aug 2013 15:03:29 +0300 Message-ID: <20130806120329.8864.36301.stgit@localhost6.localdomain6> User-Agent: StGit/0.16 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130806_080401_122808_DD30EDCB X-CRM114-Status: GOOD ( 13.83 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [83.102.40.135 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Joern Engel , linux-usb@vger.kernel.org, David Woodhouse X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org 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@vger.kernel.org Signed-off-by: Jussi Kivilinna Acked-by: Joern Engel --- 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);