From 7e5ed9f5e012f21a1514edcf8c35b9b4cfbd96c3 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Fri, 13 Dec 2019 00:06:01 +0000 Subject: serial: Move sysrq members above At the current place members those follow are: : upf_t flags; : upstat_t status; : int hw_stopped; : unsigned int mctrl; : unsigned int timeout; : unsigned int type; : const struct uart_ops *ops; Together, they give (*ops) 8-byte align on 64-bit platforms. And `sysrq_ch` introduces 4-byte padding. On the other side, above: : struct device *dev; : unsigned char hub6; : unsigned char suspended; : unsigned char unused[2]; : const char *name; Adds another 4-byte padding. Moving sysrq members just before `hub6` allows to save 8 bytes per-uart_port on 64-bit platforms: On my gcc, x86_64 sizeof(struct uart_port) goes from 528 to 520. Signed-off-by: Dmitry Safonov Link: https://lore.kernel.org/r/20191213000657.931618-3-dima@arista.com Signed-off-by: Greg Kroah-Hartman --- include/linux/serial_core.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 2b78cc734719..bbbe57bf5163 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -161,11 +161,6 @@ struct uart_port { struct uart_icount icount; /* statistics */ struct console *cons; /* struct console, if any */ -#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ) - unsigned long sysrq; /* sysrq timeout */ - unsigned int sysrq_ch; /* char for sysrq */ -#endif - /* flags must be updated while holding port mutex */ upf_t flags; @@ -244,6 +239,12 @@ struct uart_port { resource_size_t mapbase; /* for ioremap */ resource_size_t mapsize; struct device *dev; /* parent device */ + +#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ) + unsigned long sysrq; /* sysrq timeout */ + unsigned int sysrq_ch; /* char for sysrq */ +#endif + unsigned char hub6; /* this should be in the 8250 driver */ unsigned char suspended; unsigned char unused[2]; -- cgit v1.2.3-71-gd317 From 1997e9dfdc84c8f73d6fc318355cf9e313aba183 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Fri, 13 Dec 2019 00:06:02 +0000 Subject: serial_core: Un-ifdef sysrq SUPPORT_SYSRQ The SUPPORT_SYSRQ is messy: every .c source should define it before including "serial_core.h" if sysrq is supported or struct uart_port will differ in sizes. Also this prevents moving to serial_core.c functions: uart_handle_sysrq_char(), uart_prepare_sysrq_char(), uart_unlock_and_check_sysrq(). It doesn't save many bytes in the structure, and a better way to reduce it's size would be making rs485 and iso7816 pointers. Introduce `has_sysrq` member to be used by serial line drivers further. Signed-off-by: Dmitry Safonov Link: https://lore.kernel.org/r/20191213000657.931618-4-dima@arista.com Signed-off-by: Greg Kroah-Hartman --- include/linux/serial_core.h | 77 +++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 34 deletions(-) (limited to 'include/linux') diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index bbbe57bf5163..5f761c399282 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -240,14 +240,13 @@ struct uart_port { resource_size_t mapsize; struct device *dev; /* parent device */ -#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ) unsigned long sysrq; /* sysrq timeout */ unsigned int sysrq_ch; /* char for sysrq */ -#endif + unsigned char has_sysrq; unsigned char hub6; /* this should be in the 8250 driver */ unsigned char suspended; - unsigned char unused[2]; + unsigned char unused; const char *name; /* port name */ struct attribute_group *attr_group; /* port specific attributes */ const struct attribute_group **tty_groups; /* all attributes (serial core use only) */ @@ -461,31 +460,46 @@ 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); -#if defined(SUPPORT_SYSRQ) && defined(CONFIG_MAGIC_SYSRQ_SERIAL) static inline int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) { - if (port->sysrq) { - if (ch && time_before(jiffies, port->sysrq)) { - handle_sysrq(ch); - port->sysrq = 0; - return 1; - } + if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL)) + return 0; + + if (!port->has_sysrq && !IS_ENABLED(SUPPORT_SYSRQ)) + return 0; + + if (!port->sysrq) + return 0; + + if (ch && time_before(jiffies, port->sysrq)) { + handle_sysrq(ch); port->sysrq = 0; + return 1; } + port->sysrq = 0; + return 0; } static inline int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch) { - if (port->sysrq) { - if (ch && time_before(jiffies, port->sysrq)) { - port->sysrq_ch = ch; - port->sysrq = 0; - return 1; - } + if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL)) + return 0; + + if (!port->has_sysrq && !IS_ENABLED(SUPPORT_SYSRQ)) + return 0; + + if (!port->sysrq) + return 0; + + if (ch && time_before(jiffies, port->sysrq)) { + port->sysrq_ch = ch; port->sysrq = 0; + return 1; } + port->sysrq = 0; + return 0; } static inline void @@ -493,6 +507,11 @@ uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags) { int sysrq_ch; + if (!port->has_sysrq && !IS_ENABLED(SUPPORT_SYSRQ)) { + spin_unlock_irqrestore(&port->lock, irqflags); + return; + } + sysrq_ch = port->sysrq_ch; port->sysrq_ch = 0; @@ -501,17 +520,6 @@ uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags) if (sysrq_ch) handle_sysrq(sysrq_ch); } -#else -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 /* * We do the SysRQ and SAK checking like this... @@ -523,15 +531,16 @@ static inline int uart_handle_break(struct uart_port *port) if (port->handle_break) port->handle_break(port); -#ifdef SUPPORT_SYSRQ - if (port->cons && port->cons->index == port->line) { - if (!port->sysrq) { - port->sysrq = jiffies + HZ*5; - return 1; + if (port->has_sysrq || IS_ENABLED(SUPPORT_SYSRQ)) { + if (port->cons && port->cons->index == port->line) { + if (!port->sysrq) { + port->sysrq = jiffies + HZ*5; + return 1; + } + port->sysrq = 0; } - port->sysrq = 0; } -#endif + if (port->flags & UPF_SAK) do_SAK(state->port.tty); return 0; -- cgit v1.2.3-71-gd317 From d68fefdd5b5f107403568c8a4650e858132bd83a Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Fri, 13 Dec 2019 00:06:04 +0000 Subject: tty/serial: Migrate 8250_fsl to use has_sysrq The SUPPORT_SYSRQ ifdeffery is not nice as: - May create misunderstanding about sizeof(struct uart_port) between different objects - Prevents moving functions from serial_core.h - Reduces readability (well, it's ifdeffery - it's hard to follow) In order to remove SUPPORT_SYSRQ, has_sysrq variable has been added. Initialise it in driver's probe and remove ifdeffery. In contrast to 8250/8250_of, legacy_serial on powerpc does fill (struct plat_serial8250_port). The reason is likely that it's done on device_initcall(), not on probe. So, 8250_core is not yet probed. Propagate value from platform_device on 8250 probe - in case powepc legacy driver it's initialized on initcall, in case 8250_of it will be initialized later on of_platform_serial_setup(). Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Dmitry Safonov Link: https://lore.kernel.org/r/20191213000657.931618-6-dima@arista.com Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/legacy_serial.c | 4 +++- drivers/tty/serial/8250/8250_core.c | 1 + drivers/tty/serial/8250/8250_fsl.c | 4 ---- drivers/tty/serial/8250/8250_of.c | 4 +++- include/linux/serial_8250.h | 1 + 5 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index 7cea5978f21f..f061e06e9f51 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c @@ -479,8 +479,10 @@ static void __init fixup_port_irq(int index, port->irq = virq; #ifdef CONFIG_SERIAL_8250_FSL - if (of_device_is_compatible(np, "fsl,ns16550")) + if (of_device_is_compatible(np, "fsl,ns16550")) { port->handle_irq = fsl8250_handle_irq; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); + } #endif } diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index e682390ce0de..0894a22fd702 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -816,6 +816,7 @@ static int serial8250_probe(struct platform_device *dev) uart.port.flags = p->flags; uart.port.mapbase = p->mapbase; uart.port.hub6 = p->hub6; + uart.port.has_sysrq = p->has_sysrq; uart.port.private_data = p->private_data; uart.port.type = p->type; uart.port.serial_in = p->serial_in; diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c index aa0e216d5ead..0d0c80905c58 100644 --- a/drivers/tty/serial/8250/8250_fsl.c +++ b/drivers/tty/serial/8250/8250_fsl.c @@ -1,8 +1,4 @@ // SPDX-License-Identifier: GPL-2.0 -#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -#define SUPPORT_SYSRQ -#endif - #include #include diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 92fbf46ce3bd..531ad67395e0 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -222,8 +222,10 @@ static int of_platform_serial_setup(struct platform_device *ofdev, if (IS_ENABLED(CONFIG_SERIAL_8250_FSL) && (of_device_is_compatible(np, "fsl,ns16550") || - of_device_is_compatible(np, "fsl,16550-FIFO64"))) + of_device_is_compatible(np, "fsl,16550-FIFO64"))) { port->handle_irq = fsl8250_handle_irq; + port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE); + } return 0; err_unprepare: diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index bb2bc99388ca..6a8e8c48c882 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -25,6 +25,7 @@ struct plat_serial8250_port { unsigned char regshift; /* register shift */ unsigned char iotype; /* UPIO_* */ unsigned char hub6; + unsigned char has_sysrq; /* supports magic SysRq */ upf_t flags; /* UPF_* flags */ unsigned int type; /* If UPF_FIXED_TYPE */ unsigned int (*serial_in)(struct uart_port *, int); -- cgit v1.2.3-71-gd317 From 82cfd2e62b354840af6a045e084f6e9e7c49584d Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Fri, 13 Dec 2019 00:06:53 +0000 Subject: serial_core: Remove SUPPORT_SYSRQ ifdeffery No one defines it anymore. Signed-off-by: Dmitry Safonov Link: https://lore.kernel.org/r/20191213000657.931618-55-dima@arista.com Signed-off-by: Greg Kroah-Hartman --- include/linux/serial_core.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 5f761c399282..9cf1682dc580 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -466,10 +466,7 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL)) return 0; - if (!port->has_sysrq && !IS_ENABLED(SUPPORT_SYSRQ)) - return 0; - - if (!port->sysrq) + if (!port->has_sysrq || !port->sysrq) return 0; if (ch && time_before(jiffies, port->sysrq)) { @@ -487,10 +484,7 @@ uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch) if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL)) return 0; - if (!port->has_sysrq && !IS_ENABLED(SUPPORT_SYSRQ)) - return 0; - - if (!port->sysrq) + if (!port->has_sysrq || !port->sysrq) return 0; if (ch && time_before(jiffies, port->sysrq)) { @@ -507,7 +501,7 @@ uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags) { int sysrq_ch; - if (!port->has_sysrq && !IS_ENABLED(SUPPORT_SYSRQ)) { + if (!port->has_sysrq) { spin_unlock_irqrestore(&port->lock, irqflags); return; } @@ -531,7 +525,7 @@ static inline int uart_handle_break(struct uart_port *port) if (port->handle_break) port->handle_break(port); - if (port->has_sysrq || IS_ENABLED(SUPPORT_SYSRQ)) { + if (port->has_sysrq) { if (port->cons && port->cons->index == port->line) { if (!port->sysrq) { port->sysrq = jiffies + HZ*5; -- cgit v1.2.3-71-gd317 From 8e20fc3917117b42de316e87f073a1ca43d94c9f Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Thu, 9 Jan 2020 21:54:42 +0000 Subject: serial_core: Move sysrq functions from header file It's not worth to have them in every serial driver and I'm about to add another helper function. Signed-off-by: Dmitry Safonov Link: https://lore.kernel.org/r/20200109215444.95995-2-dima@arista.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 83 +++++++++++++++++++++++++++++++++++++++ include/linux/serial_core.h | 84 +++------------------------------------- 2 files changed, 88 insertions(+), 79 deletions(-) (limited to 'include/linux') diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 7b87c08f5bcb..76e506ee335c 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -3082,6 +3082,89 @@ void uart_insert_char(struct uart_port *port, unsigned int status, } EXPORT_SYMBOL_GPL(uart_insert_char); +int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) +{ + if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL)) + return 0; + + if (!port->has_sysrq || !port->sysrq) + return 0; + + if (ch && time_before(jiffies, port->sysrq)) { + handle_sysrq(ch); + port->sysrq = 0; + return 1; + } + port->sysrq = 0; + + return 0; +} +EXPORT_SYMBOL_GPL(uart_handle_sysrq_char); + +int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch) +{ + if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL)) + return 0; + + if (!port->has_sysrq || !port->sysrq) + return 0; + + if (ch && time_before(jiffies, port->sysrq)) { + port->sysrq_ch = ch; + port->sysrq = 0; + return 1; + } + port->sysrq = 0; + + return 0; +} +EXPORT_SYMBOL_GPL(uart_prepare_sysrq_char); + +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); +} +EXPORT_SYMBOL_GPL(uart_unlock_and_check_sysrq); + +/* + * We do the SysRQ and SAK checking like this... + */ +int uart_handle_break(struct uart_port *port) +{ + struct uart_state *state = port->state; + + if (port->handle_break) + port->handle_break(port); + + if (port->has_sysrq) { + if (port->cons && port->cons->index == port->line) { + if (!port->sysrq) { + port->sysrq = jiffies + HZ*5; + return 1; + } + port->sysrq = 0; + } + } + + if (port->flags & UPF_SAK) + do_SAK(state->port.tty); + return 0; +} +EXPORT_SYMBOL_GPL(uart_handle_break); + EXPORT_SYMBOL(uart_write_wakeup); EXPORT_SYMBOL(uart_register_driver); EXPORT_SYMBOL(uart_unregister_driver); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 9cf1682dc580..255e86a474e9 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -460,85 +460,11 @@ 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); -static inline int -uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) -{ - if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL)) - return 0; - - if (!port->has_sysrq || !port->sysrq) - return 0; - - if (ch && time_before(jiffies, port->sysrq)) { - handle_sysrq(ch); - port->sysrq = 0; - return 1; - } - port->sysrq = 0; - - return 0; -} -static inline int -uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch) -{ - if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL)) - return 0; - - if (!port->has_sysrq || !port->sysrq) - return 0; - - if (ch && time_before(jiffies, port->sysrq)) { - port->sysrq_ch = ch; - port->sysrq = 0; - 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); -} - -/* - * 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); - - if (port->has_sysrq) { - if (port->cons && port->cons->index == port->line) { - if (!port->sysrq) { - port->sysrq = jiffies + HZ*5; - return 1; - } - port->sysrq = 0; - } - } - - if (port->flags & UPF_SAK) - do_SAK(state->port.tty); - return 0; -} +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 irqflags); +extern int uart_handle_break(struct uart_port *port); /* * UART_ENABLE_MS - determine if port should enable modem status irqs -- cgit v1.2.3-71-gd317 From 7788f549ed8cfbecd75c10e1a1988812adba49d8 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Tue, 14 Jan 2020 17:19:12 +0000 Subject: serial_core: Remove unused member in uart_port It should remove the align-padding before @name. [yes, there's a "hole" in the structure now, but that's fine, no one cares. If they do care, the whole thing should be restructured using pahole to find a better ordering. Removing this field is good as some drivers have been known to abuse it for other things when they shouldn't have been doing that. -- gregkh] Signed-off-by: Dmitry Safonov Link: https://lore.kernel.org/r/20200114171912.261787-4-dima@arista.com Signed-off-by: Greg Kroah-Hartman --- include/linux/serial_core.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 255e86a474e9..52404ef1694e 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -246,7 +246,6 @@ struct uart_port { unsigned char hub6; /* this should be in the 8250 driver */ unsigned char suspended; - unsigned char unused; const char *name; /* port name */ struct attribute_group *attr_group; /* port specific attributes */ const struct attribute_group **tty_groups; /* all attributes (serial core use only) */ -- cgit v1.2.3-71-gd317