From d09a7308e9887a83abfd3176f4416d4142a265dc Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Wed, 27 Mar 2013 19:34:24 -0400 Subject: serial: samsung: Restore IRQ mask during noirq resume This closes a window where the system may hang in resume as soon as the UART interrupt is enabled and before the mask is restored. The hang occurs because the driver can't handle IRQs it thinks are masked. Signed-off-by: Michael Spang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/samsung.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/tty') diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index b386fc8a5eec..78d9c55a9f84 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1311,9 +1311,29 @@ static int s3c24xx_serial_resume(struct device *dev) return 0; } +static int s3c24xx_serial_resume_noirq(struct device *dev) +{ + struct uart_port *port = s3c24xx_dev_to_port(dev); + + if (port) { + /* restore IRQ mask */ + if (s3c24xx_serial_has_interrupt_mask(port)) { + unsigned int uintm = 0xf; + if (tx_enabled(port)) + uintm &= ~S3C64XX_UINTM_TXD_MSK; + if (rx_enabled(port)) + uintm &= ~S3C64XX_UINTM_RXD_MSK; + wr_regl(port, S3C64XX_UINTM, uintm); + } + } + + return 0; +} + static const struct dev_pm_ops s3c24xx_serial_pm_ops = { .suspend = s3c24xx_serial_suspend, .resume = s3c24xx_serial_resume, + .resume_noirq = s3c24xx_serial_resume_noirq, }; #define SERIAL_SAMSUNG_PM_OPS (&s3c24xx_serial_pm_ops) -- cgit v1.2.3