From patchwork Fri Nov 9 16:58:21 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Douglas Gilbert X-Patchwork-Id: 1721351 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 2A2B7DF264 for ; Fri, 9 Nov 2012 17:00:25 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TWrum-0004px-3q; Fri, 09 Nov 2012 16:58:44 +0000 Received: from smtp.infotech.no ([82.134.31.41]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TWrub-0004ly-Ca for linux-arm-kernel@lists.infradead.org; Fri, 09 Nov 2012 16:58:35 +0000 Received: from localhost (localhost [127.0.0.1]) by smtp.infotech.no (Postfix) with ESMTP id 846AF2041B3; Fri, 9 Nov 2012 17:58:28 +0100 (CET) X-Virus-Scanned: by amavisd-new-2.6.6 (20110518) (Debian) at infotech.no Received: from smtp.infotech.no ([127.0.0.1]) by localhost (smtp.infotech.no [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id rBtVw3uMSbNr; Fri, 9 Nov 2012 17:58:23 +0100 (CET) Received: from [192.168.48.66] (unknown [216.99.60.244]) by smtp.infotech.no (Postfix) with ESMTPA id B209120411A; Fri, 9 Nov 2012 17:58:22 +0100 (CET) Message-ID: <509D362D.3040605@interlog.com> Date: Fri, 09 Nov 2012 11:58:21 -0500 From: Douglas Gilbert User-Agent: Mozilla/5.0 (X11; Linux i686; rv:16.0) Gecko/20121028 Thunderbird/16.0.2 MIME-Version: 1.0 To: linux-kernel , Nicolas Ferre Subject: [PATCH] atmel_serial oops when peripheral clock misconfigured X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121109_115833_904534_B0B1B969 X-CRM114-Status: GOOD ( 12.55 ) 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 ---- ---------------------- -------------------------------------------------- -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Jean-Christophe PLAGNIOL-VILLARD , linux-arm-kernel@lists.infradead.org, Robert Nelson X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: dgilbert@interlog.com 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 In lk 3.7.0-rc4 when a peripheral clock is not found for a serial port the atmel_serial driver brings down the kernel with an oops during boot-up. This impacts the Atmel AT91 family of MCUs. For example, arch/arm/mach-at91/at91sam9x5.c does not specify properly the peripheral clocks for the UTXD0/URXD0 and UTXD1/URXD1 serial ports. Selecting either of those ports in a dts file will crash the kernel. at91sam9x5.c needs to be fixed but stopping atmel_serial crashing the kernel is more urgent. Patch attached for your consideration. Signed-of-by: Douglas Gilbert diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 3d7e1ee..cc385e0 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1457,8 +1457,9 @@ static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port, /* * Configure the port from the platform device resource info. + * Returns 0 for success or 1 in case of error. */ -static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, +static int __devinit atmel_init_port(struct atmel_uart_port *atmel_port, struct platform_device *pdev) { struct uart_port *port = &atmel_port->uart; @@ -1496,6 +1497,8 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, /* for console, the clock could already be configured */ if (!atmel_port->clk) { atmel_port->clk = clk_get(&pdev->dev, "usart"); + if (IS_ERR(atmel_port->clk)) + return 1; /* peripheral clock not found */ clk_enable(atmel_port->clk); port->uartclk = clk_get_rate(atmel_port->clk); clk_disable(atmel_port->clk); @@ -1511,6 +1514,7 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, } else { atmel_port->tx_done_mask = ATMEL_US_TXRDY; } + return 0; } /* @@ -1666,13 +1670,18 @@ static int __init atmel_console_init(void) struct atmel_uart_data *pdata = atmel_default_console_device->dev.platform_data; int id = pdata->num; + int ret; struct atmel_uart_port *port = &atmel_ports[id]; port->backup_imr = 0; port->uart.line = id; add_preferred_console(ATMEL_DEVICENAME, id, NULL); - atmel_init_port(port, atmel_default_console_device); + ret = atmel_init_port(port, atmel_default_console_device); + if (ret) { + pr_err("No peripheral clock for Atmel console ??\n"); + return -EINVAL; + } register_console(&atmel_console); } @@ -1803,7 +1812,12 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev) port->backup_imr = 0; port->uart.line = ret; - atmel_init_port(port, pdev); + ret = atmel_init_port(port, pdev); + if (ret) { + ret = -EINVAL; + pr_err("peripheral clock not found for serial port\n"); + goto err; + } if (!atmel_use_dma_rx(&port->uart)) { ret = -ENOMEM;