From patchwork Fri Jul 15 15:04:02 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nick Bowler X-Patchwork-Id: 978632 Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p6FGrwKO024145 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 15 Jul 2011 16:54:18 GMT Received: from canuck.infradead.org ([2001:4978:20e::1]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QhleA-0004XG-DC; Fri, 15 Jul 2011 16:53:50 +0000 Received: from localhost ([127.0.0.1] helo=canuck.infradead.org) by canuck.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1Qhjxe-0006KB-Qa; Fri, 15 Jul 2011 15:05:50 +0000 Received: from casper.infradead.org ([2001:770:15f::2]) by canuck.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1Qhjwd-00066R-LJ for linux-arm-kernel@canuck.infradead.org; Fri, 15 Jul 2011 15:04:47 +0000 Received: from mail.elliptictech.com ([209.217.122.41] helo=mail.ellipticsemi.com) by casper.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1QhjwX-0000Q2-90 for linux-arm-kernel@lists.infradead.org; Fri, 15 Jul 2011 15:04:46 +0000 Received: from nbowler by mail.ellipticsemi.com with local (Exim 4.76) (envelope-from ) id 1Qhjw6-0003pu-W4; Fri, 15 Jul 2011 11:04:15 -0400 From: Nick Bowler To: linux-arm-kernel@lists.infradead.org, linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/3] watchdog: sp805: Flush posted writes in enable/disable. Date: Fri, 15 Jul 2011 11:04:02 -0400 Message-Id: <1310742242-14647-4-git-send-email-nbowler@elliptictech.com> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <1310742242-14647-1-git-send-email-nbowler@elliptictech.com> References: <1310742242-14647-1-git-send-email-nbowler@elliptictech.com> X-CRM114-Version: 20090807-BlameThorstenAndJenny ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20110715_160441_712208_A7743F00 X-CRM114-Status: GOOD ( 10.32 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on casper.infradead.org summary: Content analysis details: (-1.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Wim Van Sebroeck , Russell King X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Fri, 15 Jul 2011 16:54:18 +0000 (UTC) There are no reads in these functions, so if MMIO writes are posted, the writes in enable/disable may not have completed by the time these functions return. If the functions run from different CPUs, it's in theory possible for the writes to be interleaved, which would be disastrous for this driver. At the very least, we need an mmiowb() before releasing the lock, but since it seems desirable for the watchdog timer to be actually stopped or reset when these functions return, read the lock register to force the writes out. Signed-off-by: Nick Bowler --- drivers/watchdog/sp805_wdt.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index c1e099a..cc2cfbe 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -134,6 +134,8 @@ static void wdt_enable(void) writel(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL); writel(LOCK, wdt->base + WDTLOCK); + /* Flush posted writes. */ + readl(wdt->base + WDTLOCK); spin_unlock(&wdt->lock); } @@ -146,6 +148,8 @@ static void wdt_disable(void) writel(0, wdt->base + WDTCONTROL); writel(LOCK, wdt->base + WDTLOCK); + /* Flush posted writes. */ + readl(wdt->base + WDTLOCK); spin_unlock(&wdt->lock); }