From patchwork Mon Feb 7 16:07:11 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joakim Tjernlund X-Patchwork-Id: 82116 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 1CEA5B70DE for ; Tue, 8 Feb 2011 03:09:14 +1100 (EST) Received: from canuck.infradead.org ([2001:4978:20e::1]) by bombadil.infradead.org with esmtps (Exim 4.72 #1 (Red Hat Linux)) id 1PmTcY-0002wq-JK; Mon, 07 Feb 2011 16:07:22 +0000 Received: from localhost ([127.0.0.1] helo=canuck.infradead.org) by canuck.infradead.org with esmtp (Exim 4.72 #1 (Red Hat Linux)) id 1PmTcX-0001Md-37; Mon, 07 Feb 2011 16:07:21 +0000 Received: from gw1.transmode.se ([213.115.205.20]) by canuck.infradead.org with esmtps (Exim 4.72 #1 (Red Hat Linux)) id 1PmTcT-0001MK-6w for linux-mtd@lists.infradead.org; Mon, 07 Feb 2011 16:07:18 +0000 Received: from sesr04.transmode.se (sesr04.transmode.se [192.168.201.15]) by gw1.transmode.se (Postfix) with ESMTP id AD98E650002; Mon, 7 Feb 2011 17:07:15 +0100 (CET) Received: from gentoo-jocke.transmode.se ([192.168.1.15]) by sesr04.transmode.se (Lotus Domino Release 8.5.2FP1) with ESMTP id 2011020717071542-12188 ; Mon, 7 Feb 2011 17:07:15 +0100 Received: from gentoo-jocke.transmode.se (gentoo-jocke.transmode.se [127.0.0.1]) by gentoo-jocke.transmode.se (8.14.4/8.14.0) with ESMTP id p17G7F4W010386; Mon, 7 Feb 2011 17:07:15 +0100 Received: (from jocke@localhost) by gentoo-jocke.transmode.se (8.14.4/8.14.4/Submit) id p17G7ECK010385; Mon, 7 Feb 2011 17:07:14 +0100 From: Joakim Tjernlund To: linux-mtd@lists.infradead.org, Stefan Bigler , Michael Cashwell Subject: [PATCH] mtd: fix race in cfi_cmdset_0001 driver Date: Mon, 7 Feb 2011 17:07:11 +0100 Message-Id: <1297094831-10330-1-git-send-email-Joakim.Tjernlund@transmode.se> X-Mailer: git-send-email 1.7.3.4 X-MIMETrack: Itemize by SMTP Server on sesr04/Transmode(Release 8.5.2FP1|November 29, 2010) at 2011-02-07 17:07:15, Serialize by Router on sesr04/Transmode(Release 8.5.2FP1|November 29, 2010) at 2011-02-07 17:07:15, Serialize complete at 2011-02-07 17:07:15 X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.7.6 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20110207_110717_563397_4635009E X-CRM114-Status: GOOD ( 12.57 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.3.1 on canuck.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 T_RP_MATCHES_RCVD Envelope sender domain matches handover relay domain Cc: Joakim Tjernlund X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-mtd-bounces@lists.infradead.org Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org As inval_cache_and_wait_for_operation() drop and reclaim the lock to invalidate the cache, some other thread may suspend the operation before reaching the for(;;) loop. Therefore the loop must start with checking the chip->state before reading status from the chip. Signed-off-by: Joakim Tjernlund Acked-by: Stefan Bigler Acked-by: Michael Cashwell --- David, I think this should go to Linus asap. Stefan and Michael, would be great if you could reply with a Acked-By: too. drivers/mtd/chips/cfi_cmdset_0001.c | 43 ++++++++++++++++++----------------- 1 files changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index e89f2d0..9772a62 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -1245,10 +1245,32 @@ static int inval_cache_and_wait_for_operation( sleep_time = chip_op_time / 2; for (;;) { + if (chip->state != chip_state) { + /* Someone's suspended the operation: sleep */ + DECLARE_WAITQUEUE(wait, current); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + mutex_unlock(&chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + mutex_lock(&chip->mutex); + continue; + } + status = map_read(map, cmd_adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; + if (chip->erase_suspended && chip_state == FL_ERASING) { + /* Erase suspend occured while sleep: reset timeout */ + timeo = reset_timeo; + chip->erase_suspended = 0; + } + if (chip->write_suspended && chip_state == FL_WRITING) { + /* Write suspend occured while sleep: reset timeout */ + timeo = reset_timeo; + chip->write_suspended = 0; + } if (!timeo) { map_write(map, CMD(0x70), cmd_adr); chip->state = FL_STATUS; @@ -1272,27 +1294,6 @@ static int inval_cache_and_wait_for_operation( timeo--; } mutex_lock(&chip->mutex); - - while (chip->state != chip_state) { - /* Someone's suspended the operation: sleep */ - DECLARE_WAITQUEUE(wait, current); - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - mutex_unlock(&chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); - mutex_lock(&chip->mutex); - } - if (chip->erase_suspended && chip_state == FL_ERASING) { - /* Erase suspend occured while sleep: reset timeout */ - timeo = reset_timeo; - chip->erase_suspended = 0; - } - if (chip->write_suspended && chip_state == FL_WRITING) { - /* Write suspend occured while sleep: reset timeout */ - timeo = reset_timeo; - chip->write_suspended = 0; - } } /* Done and happy. */