Skip to content

Commit 9cabe26

Browse files
alcoopergregkh
authored andcommitted
serial: 8250_bcm7271: UART errors after resuming from S2
There is a small window in time during resume where the hardware flow control signal RTS can be asserted (which allows a sender to resume sending data to the UART) but the baud rate has not yet been restored. This will cause corrupted data and FRAMING, OVERRUN and BREAK errors. This is happening because the MCTRL register is shadowed in uart_port struct and is later used during resume to set the MCTRL register during both serial8250_do_startup() and uart_resume_port(). Unfortunately, serial8250_do_startup() happens before the UART baud rate is restored. The fix is to clear the shadowed mctrl value at the end of suspend and restore it at the end of resume. Fixes: 41a4694 ("serial: 8250: Add new 8250-core based Broadcom STB driver") Acked-by: Florian Fainelli <[email protected]> Signed-off-by: Al Cooper <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent bb1201d commit 9cabe26

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

drivers/tty/serial/8250/8250_bcm7271.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ struct brcmuart_priv {
237237
u32 rx_err;
238238
u32 rx_timeout;
239239
u32 rx_abort;
240+
u32 saved_mctrl;
240241
};
241242

242243
static struct dentry *brcmuart_debugfs_root;
@@ -1133,16 +1134,27 @@ static int brcmuart_remove(struct platform_device *pdev)
11331134
static int __maybe_unused brcmuart_suspend(struct device *dev)
11341135
{
11351136
struct brcmuart_priv *priv = dev_get_drvdata(dev);
1137+
struct uart_8250_port *up = serial8250_get_port(priv->line);
1138+
struct uart_port *port = &up->port;
11361139

11371140
serial8250_suspend_port(priv->line);
11381141
clk_disable_unprepare(priv->baud_mux_clk);
11391142

1143+
/*
1144+
* This will prevent resume from enabling RTS before the
1145+
* baud rate has been resored.
1146+
*/
1147+
priv->saved_mctrl = port->mctrl;
1148+
port->mctrl = 0;
1149+
11401150
return 0;
11411151
}
11421152

11431153
static int __maybe_unused brcmuart_resume(struct device *dev)
11441154
{
11451155
struct brcmuart_priv *priv = dev_get_drvdata(dev);
1156+
struct uart_8250_port *up = serial8250_get_port(priv->line);
1157+
struct uart_port *port = &up->port;
11461158
int ret;
11471159

11481160
ret = clk_prepare_enable(priv->baud_mux_clk);
@@ -1165,6 +1177,7 @@ static int __maybe_unused brcmuart_resume(struct device *dev)
11651177
start_rx_dma(serial8250_get_port(priv->line));
11661178
}
11671179
serial8250_resume_port(priv->line);
1180+
port->mctrl = priv->saved_mctrl;
11681181
return 0;
11691182
}
11701183

0 commit comments

Comments
 (0)