TTY/Serial driver fixes for 5.8-rc6
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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXxBx8g8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ykqAwCeIWhRt4Z6YdUXjT/rFycYlFKWCVsAoJodlx6C 7FoXKFoP4c72il+qgHMp =cCbW -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
7531ee3147
@ -1215,7 +1215,12 @@ static int cpm_uart_init_port(struct device_node *np,
|
||||
|
||||
pinfo->gpios[i] = NULL;
|
||||
|
||||
gpiod = devm_gpiod_get_index(dev, NULL, i, GPIOD_ASIS);
|
||||
gpiod = devm_gpiod_get_index_optional(dev, NULL, i, GPIOD_ASIS);
|
||||
|
||||
if (IS_ERR(gpiod)) {
|
||||
ret = PTR_ERR(gpiod);
|
||||
goto out_irq;
|
||||
}
|
||||
|
||||
if (gpiod) {
|
||||
if (i == GPIO_RTS || i == GPIO_DTR)
|
||||
@ -1237,6 +1242,8 @@ static int cpm_uart_init_port(struct device_node *np,
|
||||
|
||||
return cpm_uart_request_port(&pinfo->port);
|
||||
|
||||
out_irq:
|
||||
irq_dispose_mapping(pinfo->port.irq);
|
||||
out_pram:
|
||||
cpm_uart_unmap_pram(pinfo, pram);
|
||||
out_mem:
|
||||
|
@ -1698,21 +1698,21 @@ static int mxs_auart_probe(struct platform_device *pdev)
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
ret = irq;
|
||||
goto out_disable_clks;
|
||||
goto out_iounmap;
|
||||
}
|
||||
|
||||
s->port.irq = irq;
|
||||
ret = devm_request_irq(&pdev->dev, irq, mxs_auart_irq_handle, 0,
|
||||
dev_name(&pdev->dev), s);
|
||||
if (ret)
|
||||
goto out_disable_clks;
|
||||
goto out_iounmap;
|
||||
|
||||
platform_set_drvdata(pdev, s);
|
||||
|
||||
ret = mxs_auart_init_gpios(s, &pdev->dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to initialize GPIOs.\n");
|
||||
goto out_disable_clks;
|
||||
goto out_iounmap;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1720,7 +1720,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
|
||||
*/
|
||||
ret = mxs_auart_request_gpio_irq(s);
|
||||
if (ret)
|
||||
goto out_disable_clks;
|
||||
goto out_iounmap;
|
||||
|
||||
auart_port[s->port.line] = s;
|
||||
|
||||
@ -1746,6 +1746,9 @@ out_free_qpio_irq:
|
||||
mxs_auart_free_gpio_irq(s);
|
||||
auart_port[pdev->id] = NULL;
|
||||
|
||||
out_iounmap:
|
||||
iounmap(s->port.membase);
|
||||
|
||||
out_disable_clks:
|
||||
if (is_asm9260_auart(s)) {
|
||||
clk_disable_unprepare(s->clk);
|
||||
@ -1761,6 +1764,7 @@ static int mxs_auart_remove(struct platform_device *pdev)
|
||||
uart_remove_one_port(&auart_driver, &s->port);
|
||||
auart_port[pdev->id] = NULL;
|
||||
mxs_auart_free_gpio_irq(s);
|
||||
iounmap(s->port.membase);
|
||||
if (is_asm9260_auart(s)) {
|
||||
clk_disable_unprepare(s->clk);
|
||||
clk_disable_unprepare(s->clk_ahb);
|
||||
|
@ -41,8 +41,6 @@ static struct lock_class_key port_lock_key;
|
||||
|
||||
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
|
||||
|
||||
#define SYSRQ_TIMEOUT (HZ * 5)
|
||||
|
||||
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
|
||||
struct ktermios *old_termios);
|
||||
static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
|
||||
@ -1916,6 +1914,12 @@ static inline bool uart_console_enabled(struct uart_port *port)
|
||||
return uart_console(port) && (port->cons->flags & CON_ENABLED);
|
||||
}
|
||||
|
||||
static void __uart_port_spin_lock_init(struct uart_port *port)
|
||||
{
|
||||
spin_lock_init(&port->lock);
|
||||
lockdep_set_class(&port->lock, &port_lock_key);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that the serial console lock is initialised early.
|
||||
* If this port is a console, then the spinlock is already initialised.
|
||||
@ -1925,8 +1929,7 @@ static inline void uart_port_spin_lock_init(struct uart_port *port)
|
||||
if (uart_console(port))
|
||||
return;
|
||||
|
||||
spin_lock_init(&port->lock);
|
||||
lockdep_set_class(&port->lock, &port_lock_key);
|
||||
__uart_port_spin_lock_init(port);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
|
||||
@ -2372,6 +2375,13 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
|
||||
/* Power up port for set_mctrl() */
|
||||
uart_change_pm(state, UART_PM_STATE_ON);
|
||||
|
||||
/*
|
||||
* If this driver supports console, and it hasn't been
|
||||
* successfully registered yet, initialise spin lock for it.
|
||||
*/
|
||||
if (port->cons && !(port->cons->flags & CON_ENABLED))
|
||||
__uart_port_spin_lock_init(port);
|
||||
|
||||
/*
|
||||
* Ensure that the modem control lines are de-activated.
|
||||
* keep the DTR setting that is set in uart_set_options()
|
||||
@ -3163,7 +3173,7 @@ static DECLARE_WORK(sysrq_enable_work, uart_sysrq_on);
|
||||
* Returns false if @ch is out of enabling sequence and should be
|
||||
* handled some other way, true if @ch was consumed.
|
||||
*/
|
||||
static bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch)
|
||||
bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch)
|
||||
{
|
||||
int sysrq_toggle_seq_len = strlen(sysrq_toggle_seq);
|
||||
|
||||
@ -3186,99 +3196,9 @@ static bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch)
|
||||
port->sysrq = 0;
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static inline bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(uart_try_toggle_sysrq);
|
||||
#endif
|
||||
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(uart_prepare_sysrq_char);
|
||||
|
||||
void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long flags)
|
||||
__releases(&port->lock)
|
||||
{
|
||||
if (port->has_sysrq) {
|
||||
int sysrq_ch = port->sysrq_ch;
|
||||
|
||||
port->sysrq_ch = 0;
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
if (sysrq_ch)
|
||||
handle_sysrq(sysrq_ch);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
}
|
||||
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 && uart_console(port)) {
|
||||
if (!port->sysrq) {
|
||||
port->sysrq = jiffies + SYSRQ_TIMEOUT;
|
||||
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);
|
||||
@ -3289,8 +3209,7 @@ EXPORT_SYMBOL(uart_remove_one_port);
|
||||
|
||||
/**
|
||||
* uart_get_rs485_mode() - retrieve rs485 properties for given uart
|
||||
* @dev: uart device
|
||||
* @rs485conf: output parameter
|
||||
* @port: uart device's target port
|
||||
*
|
||||
* This function implements the device tree binding described in
|
||||
* Documentation/devicetree/bindings/serial/rs485.txt.
|
||||
|
@ -3301,6 +3301,9 @@ static int sci_probe_single(struct platform_device *dev,
|
||||
sciport->port.flags |= UPF_HARD_FLOW;
|
||||
}
|
||||
|
||||
if (sci_uart_driver.cons->index == sciport->port.line)
|
||||
spin_lock_init(&sciport->port.lock);
|
||||
|
||||
ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
|
||||
if (ret) {
|
||||
sci_cleanup_single(sciport);
|
||||
|
@ -1465,7 +1465,6 @@ static int cdns_uart_probe(struct platform_device *pdev)
|
||||
cdns_uart_uart_driver.nr = CDNS_UART_NR_PORTS;
|
||||
#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE
|
||||
cdns_uart_uart_driver.cons = &cdns_uart_console;
|
||||
cdns_uart_console.index = id;
|
||||
#endif
|
||||
|
||||
rc = uart_register_driver(&cdns_uart_uart_driver);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user