From patchwork Mon Aug 27 07:36:51 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dirk Behme X-Patchwork-Id: 1376631 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id BE153DF215 for ; Mon, 27 Aug 2012 07:39:52 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1T5tsu-0005Q6-HR; Mon, 27 Aug 2012 07:37:20 +0000 Received: from smtp2-v.fe.bosch.de ([139.15.237.6]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1T5tsd-0005Mj-Tm for linux-arm-kernel@lists.infradead.org; Mon, 27 Aug 2012 07:37:05 +0000 Received: from vsmta11.fe.internet.bosch.com (unknown [10.4.98.30]) by imta23.fe.bosch.de (Postfix) with ESMTP id 0163628C0223 for ; Mon, 27 Aug 2012 09:37:02 +0200 (CEST) Received: from localhost (vsgw4.fe.internet.bosch.com [10.4.98.12]) by vsmta11.fe.internet.bosch.com (Postfix) with SMTP id 07A1B43C02E4 for ; Mon, 27 Aug 2012 09:37:02 +0200 (CEST) Received: from FE-HUB1001.de.bosch.com (10.4.103.109) by si-hub07.de.bosch.com (10.3.153.132) with Microsoft SMTP Server (TLS) id 8.3.264.0; Mon, 27 Aug 2012 09:36:58 +0200 Received: from hi-z5661.hi.de.bosch.com (10.34.219.178) by FE-HUB1001.de.bosch.com (10.4.103.109) with Microsoft SMTP Server id 14.2.309.2; Mon, 27 Aug 2012 09:36:57 +0200 Received: from localhost.localdomain (localhost [127.0.0.1]) by hi-z5661.hi.de.bosch.com (Postfix) with ESMTP id F3CF3408EE; Mon, 27 Aug 2012 09:36:56 +0200 (CEST) From: Dirk Behme To: , Subject: [PATCH 1/2] tty: serial: imx: console write routing is unsafe on SMP Date: Mon, 27 Aug 2012 09:36:51 +0200 Message-ID: <1346053012-25686-2-git-send-email-dirk.behme@de.bosch.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1346053012-25686-1-git-send-email-dirk.behme@de.bosch.com> References: <1346053012-25686-1-git-send-email-dirk.behme@de.bosch.com> MIME-Version: 1.0 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -6.9 (------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-6.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [139.15.237.6 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: kernel@pengutronix.de, Greg Kroah-Hartman , Sascha Hauer , Xinyu Chen , Shawn Guo , Alan Cox X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Xinyu Chen The console feature's write routing is unsafe on SMP with the startup/shutdown call. There could be several consumers of the console * the kernel printk * the init process using /dev/kmsg to call printk to show log * shell, which open /dev/console and write with sys_write() The shell goes into the normal uart open/write routing, but the other two go into the console operations. The open routing calls imx serial startup, which will write USR1/2 register without any lock and critical with imx_console_write call. Add a spin_lock for startup/shutdown/console_write routing. This patch is a port from Freescale's Android kernel. Signed-off-by: Xinyu Chen Tested-by: Dirk Behme CC: Shawn Guo CC: Sascha Hauer Acked-by: Shawn Guo --- drivers/tty/serial/imx.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index d5c689d..908178f 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -754,6 +754,7 @@ static int imx_startup(struct uart_port *port) } } + spin_lock_irqsave(&sport->port.lock, flags); /* * Finally, clear and enable interrupts */ @@ -807,7 +808,6 @@ static int imx_startup(struct uart_port *port) /* * Enable modem status interrupts */ - spin_lock_irqsave(&sport->port.lock,flags); imx_enable_ms(&sport->port); spin_unlock_irqrestore(&sport->port.lock,flags); @@ -837,10 +837,13 @@ static void imx_shutdown(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; unsigned long temp; + unsigned long flags; + spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR2); temp &= ~(UCR2_TXEN); writel(temp, sport->port.membase + UCR2); + spin_unlock_irqrestore(&sport->port.lock, flags); if (USE_IRDA(sport)) { struct imxuart_platform_data *pdata; @@ -869,12 +872,14 @@ static void imx_shutdown(struct uart_port *port) * Disable all interrupts, port and break condition. */ + spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR1); temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); if (USE_IRDA(sport)) temp &= ~(UCR1_IREN); writel(temp, sport->port.membase + UCR1); + spin_unlock_irqrestore(&sport->port.lock, flags); } static void @@ -1217,6 +1222,9 @@ imx_console_write(struct console *co, const char *s, unsigned int count) struct imx_port *sport = imx_ports[co->index]; struct imx_port_ucrs old_ucr; unsigned int ucr1; + unsigned long flags; + + spin_lock_irqsave(&sport->port.lock, flags); /* * First, save UCR1/2/3 and then disable interrupts @@ -1242,6 +1250,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count) while (!(readl(sport->port.membase + USR2) & USR2_TXDC)); imx_port_ucrs_restore(&sport->port, &old_ucr); + + spin_unlock_irqrestore(&sport->port.lock, flags); } /*