Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tty: serial: imx.c: Reset UART before activating interrupts

If the UART has been in use before this driver was loaded, IRQs might be
active and get fired as soon as we set the handler, which will crash
in the spin_lock_irqsave(&sport->port.lock, flags) because port.lock is
not initialized until the port is added at the end of probe.

Signed-off-by: David Jander <david@protonic.nl>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

David Jander and committed by
Greg Kroah-Hartman
e95044ba e9b5a982

+23 -9
+23 -9
drivers/tty/serial/imx.c
··· 1098 1098 /* half the RX buffer size */ 1099 1099 #define CTSTL 16 1100 1100 1101 + static inline void imx_reset(struct imx_port *sport) 1102 + { 1103 + int i = 100; 1104 + unsigned long temp; 1105 + 1106 + temp = readl(sport->port.membase + UCR2); 1107 + temp &= ~UCR2_SRST; 1108 + writel(temp, sport->port.membase + UCR2); 1109 + 1110 + while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i > 0)) 1111 + udelay(1); 1112 + } 1113 + 1101 1114 static int imx_startup(struct uart_port *port) 1102 1115 { 1103 1116 struct imx_port *sport = (struct imx_port *)port; 1104 - int retval, i; 1117 + int retval; 1105 1118 unsigned long flags, temp; 1106 1119 1107 1120 retval = clk_prepare_enable(sport->clk_per); ··· 1146 1133 1147 1134 spin_lock_irqsave(&sport->port.lock, flags); 1148 1135 /* Reset fifo's and state machines */ 1149 - i = 100; 1150 - 1151 - temp = readl(sport->port.membase + UCR2); 1152 - temp &= ~UCR2_SRST; 1153 - writel(temp, sport->port.membase + UCR2); 1154 - 1155 - while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i > 0)) 1156 - udelay(1); 1136 + imx_reset(sport); 1157 1137 1158 1138 /* 1159 1139 * Finally, clear and enable interrupts ··· 1980 1974 writel_relaxed(reg, sport->port.membase + UCR1); 1981 1975 1982 1976 clk_disable_unprepare(sport->clk_ipg); 1977 + 1978 + /* 1979 + * Perform a complete reset of the UART device. Needed if we don't 1980 + * come straight out of reset. 1981 + */ 1982 + writel(0, sport->port.membase + UCR2); 1983 + writel(0, sport->port.membase + UCR1); 1984 + imx_reset(sport); 1983 1985 1984 1986 /* 1985 1987 * Allocate the IRQ(s) i.MX1 has three interrupts whereas later