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

serial: do not restore interrupt state in sysrq helper

The uart_unlock_and_check_sysrq() helper can be used to defer processing
of sysrq until the interrupt handler has released the port lock and is
about to return.

Since commit 81e2073c175b ("genirq: Disable interrupts for force
threaded handlers") interrupt handlers that are not explicitly requested
as threaded are always called with interrupts disabled and there is no
need to save the interrupt state when taking the port lock.

Instead of adding another sysrq helper for when the interrupt state has
not needlessly been saved, drop the state parameter from
uart_unlock_and_check_sysrq() and update its callers to no longer
explicitly disable interrupts in their interrupt handlers.

Cc: Joel Stanley <joel@jms.id.au>
Cc: Andrew Jeffery <andrew@aj.id.au>
Cc: Andy Gross <agross@kernel.org>
Cc: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Link: https://lore.kernel.org/r/20210416140557.25177-2-johan@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Johan Hovold and committed by
Greg Kroah-Hartman
75f4e830 86eb0326

+22 -22
+2 -3
drivers/tty/serial/8250/8250_aspeed_vuart.c
··· 320 320 { 321 321 struct uart_8250_port *up = up_to_u8250p(port); 322 322 unsigned int iir, lsr; 323 - unsigned long flags; 324 323 int space, count; 325 324 326 325 iir = serial_port_in(port, UART_IIR); ··· 327 328 if (iir & UART_IIR_NO_INT) 328 329 return 0; 329 330 330 - spin_lock_irqsave(&port->lock, flags); 331 + spin_lock(&port->lock); 331 332 332 333 lsr = serial_port_in(port, UART_LSR); 333 334 ··· 363 364 if (lsr & UART_LSR_THRE) 364 365 serial8250_tx_chars(up); 365 366 366 - uart_unlock_and_check_sysrq(port, flags); 367 + uart_unlock_and_check_sysrq(port); 367 368 368 369 return 1; 369 370 }
+6 -5
drivers/tty/serial/8250/8250_fsl.c
··· 30 30 int fsl8250_handle_irq(struct uart_port *port) 31 31 { 32 32 unsigned char lsr, orig_lsr; 33 - unsigned long flags; 34 33 unsigned int iir; 35 34 struct uart_8250_port *up = up_to_u8250p(port); 36 35 37 - spin_lock_irqsave(&up->port.lock, flags); 36 + spin_lock(&up->port.lock); 38 37 39 38 iir = port->serial_in(port, UART_IIR); 40 39 if (iir & UART_IIR_NO_INT) { 41 - spin_unlock_irqrestore(&up->port.lock, flags); 40 + spin_unlock(&up->port.lock); 42 41 return 0; 43 42 } 44 43 ··· 45 46 if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) { 46 47 up->lsr_saved_flags &= ~UART_LSR_BI; 47 48 port->serial_in(port, UART_RX); 48 - spin_unlock_irqrestore(&up->port.lock, flags); 49 + spin_unlock(&up->port.lock); 49 50 return 1; 50 51 } 51 52 ··· 81 82 serial8250_tx_chars(up); 82 83 83 84 up->lsr_saved_flags = orig_lsr; 84 - uart_unlock_and_check_sysrq(&up->port, flags); 85 + 86 + uart_unlock_and_check_sysrq(&up->port); 87 + 85 88 return 1; 86 89 } 87 90 EXPORT_SYMBOL_GPL(fsl8250_handle_irq);
+3 -3
drivers/tty/serial/8250/8250_omap.c
··· 1143 1143 struct uart_8250_port *up = up_to_u8250p(port); 1144 1144 struct omap8250_priv *priv = up->port.private_data; 1145 1145 unsigned char status; 1146 - unsigned long flags; 1147 1146 u8 iir; 1148 1147 1149 1148 serial8250_rpm_get(up); ··· 1153 1154 return IRQ_HANDLED; 1154 1155 } 1155 1156 1156 - spin_lock_irqsave(&port->lock, flags); 1157 + spin_lock(&port->lock); 1157 1158 1158 1159 status = serial_port_in(port, UART_LSR); 1159 1160 ··· 1178 1179 } 1179 1180 } 1180 1181 1181 - uart_unlock_and_check_sysrq(port, flags); 1182 + uart_unlock_and_check_sysrq(port); 1183 + 1182 1184 serial8250_rpm_put(up); 1183 1185 return 1; 1184 1186 }
+3 -3
drivers/tty/serial/8250/8250_port.c
··· 1879 1879 int serial8250_handle_irq(struct uart_port *port, unsigned int iir) 1880 1880 { 1881 1881 unsigned char status; 1882 - unsigned long flags; 1883 1882 struct uart_8250_port *up = up_to_u8250p(port); 1884 1883 bool skip_rx = false; 1885 1884 1886 1885 if (iir & UART_IIR_NO_INT) 1887 1886 return 0; 1888 1887 1889 - spin_lock_irqsave(&port->lock, flags); 1888 + spin_lock(&port->lock); 1890 1889 1891 1890 status = serial_port_in(port, UART_LSR); 1892 1891 ··· 1911 1912 (up->ier & UART_IER_THRI)) 1912 1913 serial8250_tx_chars(up); 1913 1914 1914 - uart_unlock_and_check_sysrq(port, flags); 1915 + uart_unlock_and_check_sysrq(port); 1916 + 1915 1917 return 1; 1916 1918 } 1917 1919 EXPORT_SYMBOL_GPL(serial8250_handle_irq);
+3 -3
drivers/tty/serial/qcom_geni_serial.c
··· 818 818 u32 s_irq_status; 819 819 u32 geni_status; 820 820 struct uart_port *uport = dev; 821 - unsigned long flags; 822 821 bool drop_rx = false; 823 822 struct tty_port *tport = &uport->state->port; 824 823 struct qcom_geni_serial_port *port = to_dev_port(uport, uport); ··· 825 826 if (uport->suspended) 826 827 return IRQ_NONE; 827 828 828 - spin_lock_irqsave(&uport->lock, flags); 829 + spin_lock(&uport->lock); 830 + 829 831 m_irq_status = readl(uport->membase + SE_GENI_M_IRQ_STATUS); 830 832 s_irq_status = readl(uport->membase + SE_GENI_S_IRQ_STATUS); 831 833 geni_status = readl(uport->membase + SE_GENI_STATUS); ··· 861 861 qcom_geni_serial_handle_rx(uport, drop_rx); 862 862 863 863 out_unlock: 864 - uart_unlock_and_check_sysrq(uport, flags); 864 + uart_unlock_and_check_sysrq(uport); 865 865 866 866 return IRQ_HANDLED; 867 867 }
+5 -5
include/linux/serial_core.h
··· 500 500 return 0; 501 501 } 502 502 503 - static inline void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags) 503 + static inline void uart_unlock_and_check_sysrq(struct uart_port *port) 504 504 { 505 505 int sysrq_ch; 506 506 507 507 if (!port->has_sysrq) { 508 - spin_unlock_irqrestore(&port->lock, irqflags); 508 + spin_unlock(&port->lock); 509 509 return; 510 510 } 511 511 512 512 sysrq_ch = port->sysrq_ch; 513 513 port->sysrq_ch = 0; 514 514 515 - spin_unlock_irqrestore(&port->lock, irqflags); 515 + spin_unlock(&port->lock); 516 516 517 517 if (sysrq_ch) 518 518 handle_sysrq(sysrq_ch); ··· 526 526 { 527 527 return 0; 528 528 } 529 - static inline void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags) 529 + static inline void uart_unlock_and_check_sysrq(struct uart_port *port) 530 530 { 531 - spin_unlock_irqrestore(&port->lock, irqflags); 531 + spin_unlock(&port->lock); 532 532 } 533 533 #endif /* CONFIG_MAGIC_SYSRQ_SERIAL */ 534 534