summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-07-16 11:10:27 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2020-07-16 11:10:27 -0700
commit7531ee3147ed2fad5d5bbbd22880eea969dfc291 (patch)
tree0688c036d878252b0a12e941f45288c5af88917d /include
parent7e8d2f6d4d8fa6adc5075d39184c2ce713ce168e (diff)
parentf743061a85f5e9989df22ccbf07c80c98fc90e08 (diff)
Merge tag 'tty-5.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty into master
Pull tty/serial driver fixes from Greg KH: :Here are some small tty and serial driver fixes for 5.8-rc6. The largest set of patches in here is a revert of the sysrq changes that went into 5.8-rc1 but turned out to cause a noticable overhead and cpu usage. Other than that, there's a few small serial driver fixes to resolve reported issues, and finally resolving the spinlock init problem on many serial driver consoles. All of these have been in linux-next for a while with no reported issues" * tag 'tty-5.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: serial: core: Initialise spin lock before use in uart_configure_port() serial: mxs-auart: add missed iounmap() in probe failure and remove serial: sh-sci: Initialize spinlock for uart console Revert "tty: xilinx_uartps: Fix missing id assignment to the console" serial: core: drop redundant sysrq checks serial: core: fix sysrq overhead regression Revert "serial: core: Refactor uart_unlock_and_check_sysrq()" tty/serial: fix serial_core.c kernel-doc warnings tty: serial: cpm_uart: Fix behaviour for non existing GPIOs
Diffstat (limited to 'include')
-rw-r--r--include/linux/serial_core.h102
1 files changed, 98 insertions, 4 deletions
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 9fd550e7946a..791f4844efeb 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -462,10 +462,104 @@ extern void uart_handle_cts_change(struct uart_port *uport,
extern void uart_insert_char(struct uart_port *port, unsigned int status,
unsigned int overrun, unsigned int ch, unsigned int flag);
-extern int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch);
-extern int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch);
-extern void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long flags);
-extern int uart_handle_break(struct uart_port *port);
+#ifdef CONFIG_MAGIC_SYSRQ_SERIAL
+#define SYSRQ_TIMEOUT (HZ * 5)
+
+bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch);
+
+static inline int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
+{
+ if (!port->sysrq)
+ return 0;
+
+ if (ch && time_before(jiffies, port->sysrq)) {
+ if (sysrq_mask()) {
+ handle_sysrq(ch);
+ port->sysrq = 0;
+ return 1;
+ }
+ if (uart_try_toggle_sysrq(port, ch))
+ return 1;
+ }
+ port->sysrq = 0;
+
+ return 0;
+}
+
+static inline int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch)
+{
+ if (!port->sysrq)
+ return 0;
+
+ if (ch && time_before(jiffies, port->sysrq)) {
+ if (sysrq_mask()) {
+ port->sysrq_ch = ch;
+ port->sysrq = 0;
+ return 1;
+ }
+ if (uart_try_toggle_sysrq(port, ch))
+ return 1;
+ }
+ port->sysrq = 0;
+
+ return 0;
+}
+
+static inline void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags)
+{
+ int sysrq_ch;
+
+ if (!port->has_sysrq) {
+ spin_unlock_irqrestore(&port->lock, irqflags);
+ return;
+ }
+
+ sysrq_ch = port->sysrq_ch;
+ port->sysrq_ch = 0;
+
+ spin_unlock_irqrestore(&port->lock, irqflags);
+
+ if (sysrq_ch)
+ handle_sysrq(sysrq_ch);
+}
+#else /* CONFIG_MAGIC_SYSRQ_SERIAL */
+static inline int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
+{
+ return 0;
+}
+static inline int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch)
+{
+ return 0;
+}
+static inline void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags)
+{
+ spin_unlock_irqrestore(&port->lock, irqflags);
+}
+#endif /* CONFIG_MAGIC_SYSRQ_SERIAL */
+
+/*
+ * We do the SysRQ and SAK checking like this...
+ */
+static inline int uart_handle_break(struct uart_port *port)
+{
+ struct uart_state *state = port->state;
+
+ if (port->handle_break)
+ port->handle_break(port);
+
+#ifdef CONFIG_MAGIC_SYSRQ_SERIAL
+ if (port->has_sysrq && uart_console(port)) {
+ if (!port->sysrq) {
+ port->sysrq = jiffies + SYSRQ_TIMEOUT;
+ return 1;
+ }
+ port->sysrq = 0;
+ }
+#endif
+ if (port->flags & UPF_SAK)
+ do_SAK(state->port.tty);
+ return 0;
+}
/*
* UART_ENABLE_MS - determine if port should enable modem status irqs