From 958f0311136b3e47a1ce3093663f74c4ee139558 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 8 May 2018 14:15:02 -0700 Subject: serial: lpuart: Avoid division by zero when requested baudrate is With serdev device support added there's now a corner case where: 1. There is a DT node for a serdev device on one of the UARTs 2. There is no driver that binds against serdev device's compatibility string with 1 and 2 being true it is possible to end up in a situation where a particualr UART has not been initalized to any baudrate when clock_notifier_call_chain() gets called. This effectively translates to set_baudrate(uart, 0); which for LPUART driver result in a division by zero. To avoid this problem, convert lpuart_serial_setbaudrate() to treat zero baudrate as a request to disable the UART. While we are at it add a BUG_ON() to lpuart_setbrg() to simplify finding any future bugs. Signed-off-by: Andrey Smirnov Signed-off-by: Sascha Hauer --- drivers/serial/serial_lpuart.c | 13 ++++++++----- include/serial/lpuart.h | 2 ++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c index f28035a326..246fc3d3af 100644 --- a/drivers/serial/serial_lpuart.c +++ b/drivers/serial/serial_lpuart.c @@ -68,11 +68,14 @@ static int lpuart_serial_setbaudrate(struct console_device *cdev, lpuart_enable(lpuart, false); - lpuart_setbrg(lpuart->base, - clk_get_rate(lpuart->clk), - baudrate); - - lpuart_enable(lpuart, true); + /* + * We treat baudrate of 0 as a request to disable UART + */ + if (baudrate) { + lpuart_setbrg(lpuart->base, clk_get_rate(lpuart->clk), + baudrate); + lpuart_enable(lpuart, true); + } lpuart->baudrate = baudrate; diff --git a/include/serial/lpuart.h b/include/serial/lpuart.h index a920291dec..9c6e271ebf 100644 --- a/include/serial/lpuart.h +++ b/include/serial/lpuart.h @@ -228,6 +228,8 @@ static inline void lpuart_setbrg(void __iomem *base, unsigned int bfra; u16 sbr; + BUG_ON(!baudrate); + sbr = (u16) (refclock / (16 * baudrate)); writeb(sbr >> 8, base + UARTBDH); -- cgit v1.2.3