FAILED: patch "[PATCH] tty: serial: samsung: Remove redundant port lock acquisition" failed to apply to 5.10-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x a3bb136bff5e6a5e48cdd813246c9c4686feaaa9
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026060429-earflap-scope-57c7@gregkh' --subject-prefix 'PATCH 5.10.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From a3bb136bff5e6a5e48cdd813246c9c4686feaaa9 Mon Sep 17 00:00:00 2001
From: Tudor Ambarus <[email protected]>
Date: Fri, 15 May 2026 12:41:21 +0000
Subject: [PATCH] tty: serial: samsung: Remove redundant port lock acquisition
in rx helpers
Sashiko identified a deadlock when the console flow is engaged [1].
When console flow control is enabled (UPF_CONS_FLOW), s3c24xx_serial_stop_tx() calls s3c24xx_serial_rx_enable() and s3c24xx_serial_start_tx() calls s3c24xx_serial_rx_disable().
The serial core framework invokes the .stop_tx() and .start_tx() callbacks with the port->lock spinlock already held. Furthermore, all internal driver paths that invoke stop_tx (such as the DMA TX completion handler s3c24xx_serial_tx_dma_complete() or the PIO TX IRQ handler s3c24xx_serial_tx_irq()) also acquire port->lock prior to calling it. (Note that s3c24xx_serial_start_tx() is only invoked by the serial core).
However, s3c24xx_serial_rx_enable() and s3c24xx_serial_rx_disable() unconditionally attempt to acquire port->lock again using uart_port_lock_irqsave(). Since spinlocks are not recursive, this causes a deadlock on the same CPU when console flow control is engaged.
Remove the redundant lock acquisition from both rx helper functions.
drivers/tty/serial/samsung_tty.c +0 -8
@@ -245,12 +245,9 @@ static bool s3c24xx_serial_txempty_nofifo(const struct uart_port *port)static void s3c24xx_serial_rx_enable (struct uart_port *port) {struct s3c24xx_uart_port *ourport =to_ourport (port); -unsigned long flags;int count =10000 ;u32 ucon, ufcon; -uart_port_lock_irqsave (port, &flags); -while (--count && !s3c24xx_serial_txempty_nofifo (port))udelay (100 );
@@ -263,23 +260,18 @@ static void s3c24xx_serial_rx_enable(struct uart_port *port)wr_regl (port,S3C2410_UCON , ucon); ourport->rx_enabled =1 ; -uart_port_unlock_irqrestore (port, flags); }static void s3c24xx_serial_rx_disable (struct uart_port *port) {struct s3c24xx_uart_port *ourport =to_ourport (port); -unsigned long flags;u32 ucon; -uart_port_lock_irqsave (port, &flags); - ucon =rd_regl (port,S3C2410_UCON ); ucon &= ~S3C2410_UCON_RXIRQMODE ;wr_regl (port,S3C2410_UCON , ucon); ourport->rx_enabled =0 ; -uart_port_unlock_irqrestore (port, flags); }static void s3c24xx_serial_stop_tx (struct uart_port *port)
Sasha Levin
maintainerPATCH 1/3 serial: samsung_tty: Use port lock wrappers
From: Thomas Gleixner <[email protected]>
[ Upstream commit 97d7a9aeba1d424c2359f1686d02c75d798ad184 ]
When a serial port is used for kernel console output, then all modifications to the UART registers which are done from other contexts, e.g. getty, termios, are interference points for the kernel console.
So far this has been ignored and the printk output is based on the principle of hope. The rework of the console infrastructure which aims to support threaded and atomic consoles, requires to mark sections which modify the UART registers as unsafe. This allows the atomic write function to make informed decisions and eventually to restore operational state. It also allows to prevent the regular UART code from modifying UART registers while printk output is in progress.
All modifications of UART registers are guarded by the UART port lock, which provides an obvious synchronization point with the console infrastructure.
To avoid adding this functionality to all UART drivers, wrap the spin_[un]lock*() invocations for uart_port::lock into helper functions which just contain the spin_[un]lock*() invocations for now. In a subsequent step these helpers will gain the console synchronization mechanisms.
Converted with coccinelle. No functional change.
Stable-dep-of: a3bb136bff5e ("tty: serial: samsung: Remove redundant port lock acquisition in rx helpers")
--- drivers/tty/serial/samsung_tty.c | 36 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-)
drivers/tty/serial/samsung_tty.c +18 -18
@@ -245,7 +245,7 @@ static void s3c24xx_serial_rx_enable(struct uart_port *port)unsigned int ucon, ufcon;int count =10000 ; -spin_lock_irqsave (&port->lock, flags); +uart_port_lock_irqsave (port, &flags);while (--count && !s3c24xx_serial_txempty_nofifo (port))udelay (100 );
@@ -259,7 +259,7 @@ static void s3c24xx_serial_rx_enable(struct uart_port *port)wr_regl (port,S3C2410_UCON , ucon); ourport->rx_enabled =1 ; -spin_unlock_irqrestore (&port->lock, flags); +uart_port_unlock_irqrestore (port, flags); }static void s3c24xx_serial_rx_disable (struct uart_port *port)
@@ -268,14 +268,14 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port)unsigned long flags;unsigned int ucon; -spin_lock_irqsave (&port->lock, flags); +uart_port_lock_irqsave (port, &flags); ucon =rd_regl (port,S3C2410_UCON ); ucon &= ~S3C2410_UCON_RXIRQMODE ;wr_regl (port,S3C2410_UCON , ucon); ourport->rx_enabled =0 ; -spin_unlock_irqrestore (&port->lock, flags); +uart_port_unlock_irqrestore (port, flags); }static void s3c24xx_serial_stop_tx (struct uart_port *port)
@@ -334,7 +334,7 @@ static void s3c24xx_serial_tx_dma_complete(void *args)dma_sync_single_for_cpu (ourport->port.dev, dma->tx_transfer_addr, dma->tx_size,DMA_TO_DEVICE ); -spin_lock_irqsave (&port->lock, flags); +uart_port_lock_irqsave (port, &flags); xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE -1 ); port->icount.tx += count;
@@ -344,7 +344,7 @@ static void s3c24xx_serial_tx_dma_complete(void *args)uart_write_wakeup (port);s3c24xx_serial_start_next_tx (ourport); -spin_unlock_irqrestore (&port->lock, flags); +uart_port_unlock_irqrestore (port, flags); }static void enable_tx_dma (struct s3c24xx_uart_port *ourport)
@@ -579,7 +579,7 @@ static void s3c24xx_serial_rx_dma_complete(void *args) received = dma->rx_bytes_requested - state.residue;async_tx_ack (dma->rx_desc); -spin_lock_irqsave (&port->lock, flags); +uart_port_lock_irqsave (port, &flags);if (received)s3c24xx_uart_copy_rx_to_tty (ourport, t, received);
@@ -591,7 +591,7 @@ static void s3c24xx_serial_rx_dma_complete(void *args)s3c64xx_start_rx_dma (ourport); -spin_unlock_irqrestore (&port->lock, flags); +uart_port_unlock_irqrestore (port, flags); }static void s3c64xx_start_rx_dma (struct s3c24xx_uart_port *ourport)
@@ -679,7 +679,7 @@ static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id) utrstat =rd_regl (port,S3C2410_UTRSTAT );rd_regl (port,S3C2410_UFSTAT ); -spin_lock_irqsave (&port->lock, flags); +uart_port_lock_irqsave (port, &flags);if (!(utrstat &S3C2410_UTRSTAT_TIMEOUT )) {s3c64xx_start_rx_dma (ourport);
@@ -708,7 +708,7 @@ static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)wr_regl (port,S3C2410_UTRSTAT ,S3C2410_UTRSTAT_TIMEOUT ); finish: -spin_unlock_irqrestore (&port->lock, flags); +uart_port_unlock_irqrestore (port, flags);return IRQ_HANDLED ; }
@@ -806,9 +806,9 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id)struct uart_port *port = &ourport->port;unsigned long flags; -spin_lock_irqsave (&port->lock, flags); +uart_port_lock_irqsave (port, &flags);s3c24xx_serial_rx_drain_fifo (ourport); -spin_unlock_irqrestore (&port->lock, flags); +uart_port_unlock_irqrestore (port, flags);return IRQ_HANDLED ; }
@@ -956,7 +956,7 @@ static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)unsigned long flags;unsigned int ucon; -spin_lock_irqsave (&port->lock, flags); +uart_port_lock_irqsave (port, &flags); ucon =rd_regl (port,S3C2410_UCON );
@@ -967,7 +967,7 @@ static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)wr_regl (port,S3C2410_UCON , ucon); -spin_unlock_irqrestore (&port->lock, flags); +uart_port_unlock_irqrestore (port, flags); }static int s3c24xx_serial_request_dma (struct s3c24xx_uart_port *p)
@@ -1192,7 +1192,7 @@ static int s3c64xx_serial_startup(struct uart_port *port) ourport->tx_enabled =0 ; ourport->tx_claimed =1 ; -spin_lock_irqsave (&port->lock, flags); +uart_port_lock_irqsave (port, &flags); ufcon =rd_regl (port,S3C2410_UFCON ); ufcon |=S3C2410_UFCON_RESETRX |S5PV210_UFCON_RXTRIG8 ;
@@ -1202,7 +1202,7 @@ static int s3c64xx_serial_startup(struct uart_port *port)enable_rx_pio (ourport); -spin_unlock_irqrestore (&port->lock, flags); +uart_port_unlock_irqrestore (port, flags);/* Enable Rx Interrupt */ s3c24xx_clear_bit (port,S3C64XX_UINTM_RXD ,S3C64XX_UINTM );
@@ -1479,7 +1479,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, ulcon |=S3C2410_LCON_PNONE ; } -spin_lock_irqsave (&port->lock, flags); +uart_port_lock_irqsave (port, &flags); dev_dbg(port->dev, "setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
@@ -1537,7 +1537,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,if ((termios->c_cflag &CREAD ) ==0 ) port->ignore_status_mask |=RXSTAT_DUMMY_READ ; -spin_unlock_irqrestore (&port->lock, flags); +uart_port_unlock_irqrestore (port, flags); }static const char *s3c24xx_serial_type (struct uart_port *port)
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/3 tty: serial: samsung: use u32 for register interactions
From: Tudor Ambarus <[email protected]>
[ Upstream commit 032a725c16add79332d774348d7ad7d0d4b86479 ]
All registers of the IP have 32 bits. Use u32 variables when reading or writing from/to the registers. The purpose of those variables becomes clearer.
Stable-dep-of: a3bb136bff5e ("tty: serial: samsung: Remove redundant port lock acquisition in rx helpers")
--- drivers/tty/serial/samsung_tty.c | 67 ++++++++++++++++---------------- 1 file changed, 34 insertions(+), 33 deletions(-)
drivers/tty/serial/samsung_tty.c +34 -33
@@ -186,7 +186,7 @@ static void wr_reg(struct uart_port *port, u32 reg, u32 val)/* Byte-order aware bit setting/clearing functions. */ static inline void s3c24xx_set_bit (struct uart_port *port,int idx, -unsigned int reg) +u32 reg) {unsigned long flags;u32 val;
@@ -199,7 +199,7 @@ static inline void s3c24xx_set_bit(struct uart_port *port, int idx, }static inline void s3c24xx_clear_bit (struct uart_port *port,int idx, -unsigned int reg) +u32 reg) {unsigned long flags;u32 val;
@@ -242,8 +242,8 @@ static void s3c24xx_serial_rx_enable(struct uart_port *port) {struct s3c24xx_uart_port *ourport =to_ourport (port);unsigned long flags; -unsigned int ucon, ufcon;int count =10000 ; +u32 ucon, ufcon;uart_port_lock_irqsave (port, &flags);
@@ -266,7 +266,7 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port) {struct s3c24xx_uart_port *ourport =to_ourport (port);unsigned long flags; -unsigned int ucon; +u32 ucon;uart_port_lock_irqsave (port, &flags);
@@ -551,7 +551,7 @@ static inline struct s3c2410_uartcfg }static int s3c24xx_serial_rx_fifocnt (struct s3c24xx_uart_port *ourport, -unsigned long ufstat) +u32 ufstat) {struct s3c24xx_uart_info *info = ourport->info;
@@ -623,7 +623,7 @@ static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport)static void enable_rx_dma (struct s3c24xx_uart_port *ourport) {struct uart_port *port = &ourport->port; -unsigned int ucon; +u32 ucon;/* set Rx mode to DMA mode */ ucon =rd_regl (port,S3C2410_UCON );
@@ -646,7 +646,7 @@ static void enable_rx_dma(struct s3c24xx_uart_port *ourport)static void enable_rx_pio (struct s3c24xx_uart_port *ourport) {struct uart_port *port = &ourport->port; -unsigned int ucon; +u32 ucon;/* set Rx mode to DMA mode */ ucon =rd_regl (port,S3C2410_UCON );
@@ -667,7 +667,6 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport);static irqreturn_t s3c24xx_serial_rx_chars_dma (void *dev_id) { -unsigned int utrstat, received;struct s3c24xx_uart_port *ourport = dev_id;struct uart_port *port = &ourport->port;struct s3c24xx_uart_dma *dma = ourport->dma;
@@ -675,6 +674,8 @@ static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)struct tty_port *t = &port->state->port;unsigned long flags;struct dma_tx_state state; +unsigned int received; +u32 utrstat; utrstat =rd_regl (port,S3C2410_UTRSTAT );rd_regl (port,S3C2410_UFSTAT );
@@ -716,9 +717,10 @@ static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)static void s3c24xx_serial_rx_drain_fifo (struct s3c24xx_uart_port *ourport) {struct uart_port *port = &ourport->port; -unsigned int ufcon, ch, flag, ufstat, uerstat; +unsigned int ch, flag;unsigned int fifocnt =0 ;int max_count = port->fifosize; +u32 ufcon, ufstat, uerstat;while (max_count-- >0 ) {/*
@@ -898,7 +900,7 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id) {struct s3c24xx_uart_port *ourport = id;struct uart_port *port = &ourport->port; -unsigned int pend =rd_regl (port,S3C64XX_UINTP ); +u32 pend =rd_regl (port,S3C64XX_UINTP );irqreturn_t ret =IRQ_HANDLED ;if (pend &S3C64XX_UINTM_RXD_MSK ) {
@@ -915,8 +917,8 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)static unsigned int s3c24xx_serial_tx_empty (struct uart_port *port) {struct s3c24xx_uart_info *info =s3c24xx_port_to_info (port); -unsigned long ufstat =rd_regl (port,S3C2410_UFSTAT ); -unsigned long ufcon =rd_regl (port,S3C2410_UFCON ); +u32 ufstat =rd_regl (port,S3C2410_UFSTAT ); +u32 ufcon =rd_regl (port,S3C2410_UFCON );if (ufcon &S3C2410_UFCON_FIFOMODE ) { if ((ufstat & info->tx_fifomask) != 0 ||
@@ -931,7 +933,7 @@ static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)/* no modem control lines */ static unsigned int s3c24xx_serial_get_mctrl (struct uart_port *port) { -unsigned int umstat =rd_reg (port,S3C2410_UMSTAT ); +u32 umstat =rd_reg (port,S3C2410_UMSTAT );if (umstat &S3C2410_UMSTAT_CTS )return TIOCM_CAR |TIOCM_DSR |TIOCM_CTS ;
@@ -941,7 +943,7 @@ static unsigned int s3c24xx_serial_get_mctrl(struct uart_port *port)static void s3c24xx_serial_set_mctrl (struct uart_port *port,unsigned int mctrl) { -unsigned int umcon =rd_regl (port,S3C2410_UMCON ); +u32 umcon =rd_regl (port,S3C2410_UMCON );if (mctrl &TIOCM_RTS ) umcon |=S3C2410_UMCOM_RTS_LOW ;
@@ -954,7 +956,7 @@ static void s3c24xx_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)static void s3c24xx_serial_break_ctl (struct uart_port *port,int break_state) {unsigned long flags; -unsigned int ucon; +u32 ucon;uart_port_lock_irqsave (port, &flags);
@@ -1167,7 +1169,7 @@ static int s3c64xx_serial_startup(struct uart_port *port) {struct s3c24xx_uart_port *ourport =to_ourport (port);unsigned long flags; -unsigned int ufcon; +u32 ufcon;int ret;wr_regl (port,S3C64XX_UINTM ,0xf );
@@ -1210,6 +1212,7 @@ static int s3c64xx_serial_startup(struct uart_port *port)return ret; } +/* power power management control */ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
@@ -1261,7 +1264,7 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,static inline int s3c24xx_serial_getsource (struct uart_port *port) {struct s3c24xx_uart_info *info =s3c24xx_port_to_info (port); -unsigned int ucon; +u32 ucon;if (info->num_clks ==1 )return 0 ;
@@ -1275,7 +1278,7 @@ static void s3c24xx_serial_setsource(struct uart_port *port, unsigned int clk_sel) {struct s3c24xx_uart_info *info =s3c24xx_port_to_info (port); -unsigned int ucon; +u32 ucon;if (info->num_clks ==1 )return ;
@@ -1394,9 +1397,8 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,struct clk *clk =ERR_PTR (-EINVAL );unsigned long flags;unsigned int baud, quot, clk_sel =0 ; -unsigned int ulcon; -unsigned int umcon;unsigned int udivslot =0 ; +u32 ulcon, umcon;/* * We don't support modem control lines.
@@ -1712,7 +1714,7 @@ static void s3c24xx_serial_resetport(struct uart_port *port, struct s3c2410_uartcfg *cfg) {struct s3c24xx_uart_info *info =s3c24xx_port_to_info (port); -unsigned long ucon =rd_regl (port,S3C2410_UCON ); +u32 ucon =rd_regl (port,S3C2410_UCON );unsigned int ucon_mask; ucon_mask = info->clksel_mask;
@@ -2150,7 +2152,7 @@ static int s3c24xx_serial_resume_noirq(struct device *dev)if (port) {/* restore IRQ mask */ if (s3c24xx_serial_has_interrupt_mask (port)) { -unsigned int uintm =0xf ; +u32 uintm =0xf ;if (ourport->tx_enabled) uintm &= ~S3C64XX_UINTM_TXD_MSK ;
@@ -2188,10 +2190,10 @@ static const struct dev_pm_ops s3c24xx_serial_pm_ops = {static struct uart_port *cons_uart;static int -s3c24xx_serial_console_txrdy (struct uart_port *port,unsigned int ufcon) +s3c24xx_serial_console_txrdy (struct uart_port *port,u32 ufcon) {struct s3c24xx_uart_info *info =s3c24xx_port_to_info (port); -unsigned long ufstat, utrstat; +u32 ufstat, utrstat;if (ufcon &S3C2410_UFCON_FIFOMODE ) {/* fifo mode - check amount of data in fifo registers... */
@@ -2207,7 +2209,7 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon) }static bool -s3c24xx_port_configured (unsigned int ucon) +s3c24xx_port_configured (u32 ucon) {/* consider the serial port configured if the tx/rx mode set */ return (ucon &0xf ) !=0 ;
@@ -2222,7 +2224,7 @@ s3c24xx_port_configured(unsigned int ucon)static int s3c24xx_serial_get_poll_char (struct uart_port *port) {struct s3c24xx_uart_port *ourport =to_ourport (port); -unsigned int ufstat; +u32 ufstat; ufstat =rd_regl (port,S3C2410_UFSTAT );if (s3c24xx_serial_rx_fifocnt (ourport, ufstat) ==0 )
@@ -2234,8 +2236,8 @@ static int s3c24xx_serial_get_poll_char(struct uart_port *port)static void s3c24xx_serial_put_poll_char (struct uart_port *port,unsigned char c) { -unsigned int ufcon =rd_regl (port,S3C2410_UFCON ); -unsigned int ucon =rd_regl (port,S3C2410_UCON ); +u32 ufcon =rd_regl (port,S3C2410_UFCON ); +u32 ucon =rd_regl (port,S3C2410_UCON );/* not possible to xmit on unconfigured port */ if (!s3c24xx_port_configured (ucon))
@@ -2251,7 +2253,7 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,static void s3c24xx_serial_console_putchar (struct uart_port *port,int ch) { -unsigned int ufcon =rd_regl (port,S3C2410_UFCON ); +u32 ufcon =rd_regl (port,S3C2410_UFCON );while (!s3c24xx_serial_console_txrdy (port, ufcon))cpu_relax ();
@@ -2262,7 +2264,7 @@ static void s3c24xx_serial_console_write(struct console *co, const char *s, unsigned int count) { - unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON); + u32 ucon = rd_regl(cons_uart, S3C2410_UCON);/* not possible to xmit on unconfigured port */ if (!s3c24xx_port_configured (ucon))
@@ -2276,11 +2278,9 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, int *parity, int *bits) { struct clk *clk; -unsigned int ulcon; -unsigned int ucon; -unsigned int ubrdiv;unsigned long rate;unsigned int clk_sel; +u32 ulcon, ucon, ubrdiv;char clk_name[MAX_CLK_NAME_LENGTH ]; ulcon =rd_regl (port,S3C2410_ULCON );
@@ -2677,6 +2677,7 @@ static void samsung_early_write(struct console *con, const char *s,uart_console_write (&dev->port, s, n, samsung_early_putc); } +static int __init samsung_early_console_setup (struct earlycon_device *device,const char *opt) {
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/3 tty: serial: samsung: Remove redundant port lock acquisition in rx helpers
In reply to Sasha LevinFrom: Tudor Ambarus <[email protected]>
[ Upstream commit a3bb136bff5e6a5e48cdd813246c9c4686feaaa9 ]
Sashiko identified a deadlock when the console flow is engaged [1].
When console flow control is enabled (UPF_CONS_FLOW), s3c24xx_serial_stop_tx() calls s3c24xx_serial_rx_enable() and s3c24xx_serial_start_tx() calls s3c24xx_serial_rx_disable().
The serial core framework invokes the .stop_tx() and .start_tx() callbacks with the port->lock spinlock already held. Furthermore, all internal driver paths that invoke stop_tx (such as the DMA TX completion handler s3c24xx_serial_tx_dma_complete() or the PIO TX IRQ handler s3c24xx_serial_tx_irq()) also acquire port->lock prior to calling it. (Note that s3c24xx_serial_start_tx() is only invoked by the serial core).
However, s3c24xx_serial_rx_enable() and s3c24xx_serial_rx_disable() unconditionally attempt to acquire port->lock again using uart_port_lock_irqsave(). Since spinlocks are not recursive, this causes a deadlock on the same CPU when console flow control is engaged.
Remove the redundant lock acquisition from both rx helper functions.
--- drivers/tty/serial/samsung_tty.c | 8 -------- 1 file changed, 8 deletions(-)
drivers/tty/serial/samsung_tty.c +0 -8
@@ -241,12 +241,9 @@ static int s3c24xx_serial_has_interrupt_mask(struct uart_port *port)static void s3c24xx_serial_rx_enable (struct uart_port *port) {struct s3c24xx_uart_port *ourport =to_ourport (port); -unsigned long flags;int count =10000 ;u32 ucon, ufcon; -uart_port_lock_irqsave (port, &flags); -while (--count && !s3c24xx_serial_txempty_nofifo (port))udelay (100 );
@@ -259,23 +256,18 @@ static void s3c24xx_serial_rx_enable(struct uart_port *port)wr_regl (port,S3C2410_UCON , ucon); ourport->rx_enabled =1 ; -uart_port_unlock_irqrestore (port, flags); }static void s3c24xx_serial_rx_disable (struct uart_port *port) {struct s3c24xx_uart_port *ourport =to_ourport (port); -unsigned long flags;u32 ucon; -uart_port_lock_irqsave (port, &flags); - ucon =rd_regl (port,S3C2410_UCON ); ucon &= ~S3C2410_UCON_RXIRQMODE ;wr_regl (port,S3C2410_UCON , ucon); ourport->rx_enabled =0 ; -uart_port_unlock_irqrestore (port, flags); }static void s3c24xx_serial_stop_tx (struct uart_port *port)
Signature · 1 line
2.53.0