Some serial 8250 devices may work with very high speed. While was using QEMU KVM was observed speed 1..100 Mbit/sec, it fully depends at host machine. It may affects on responsiveness of system due a cpu would be spinning in 8250 driver at burst. So added opportunity to put this processing in kthread. Signed-off-by: Denys Zagorui <dzagorui@xxxxxxxxx> --- drivers/tty/serial/8250/8250_core.c | 29 +++++++++++++++++++++++++++++ drivers/tty/serial/8250/8250_port.c | 10 ++++++++++ drivers/tty/serial/8250/Kconfig | 10 ++++++++++ 3 files changed, 49 insertions(+) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 1aab3010fbfa..7b498d2e882b 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -58,7 +58,11 @@ static struct uart_driver serial8250_reg; static unsigned int skip_txen_test; /* force skip of txen test at init time */ +#ifdef CONFIG_SERIAL_8250_THREADED_IRQ +#define PASS_LIMIT 32 +#else #define PASS_LIMIT 512 +#endif #include <asm/serial.h> /* @@ -135,10 +139,16 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) l = l->next; if (l == i->head && pass_counter++ > PASS_LIMIT) { +#ifdef CONFIG_SERIAL_8250_THREADED_IRQ + cond_resched(); + pass_counter = 0; +#else /* If we hit this, we're dead. */ printk_ratelimited(KERN_ERR "serial8250: too much work for irq%d\n", irq); break; + +#endif } } while (l != end); @@ -146,9 +156,23 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) pr_debug("%s(%d): end\n", __func__, irq); +#ifdef CONFIG_SERIAL_8250_THREADED_IRQ + enable_irq(i->irq); +#endif return IRQ_RETVAL(handled); } +#ifdef CONFIG_SERIAL_8250_THREADED_IRQ +static irqreturn_t serial8250_hard_irq(int irq, void *dev_id) +{ + struct irq_info *i = dev_id; + + disable_irq_nosync(i->irq); + + return IRQ_WAKE_THREAD; +} +#endif + /* * To support ISA shared interrupts, we need to have one interrupt * handler that ensures that the IRQ line has been deasserted @@ -217,8 +241,13 @@ static int serial_link_irq_chain(struct uart_8250_port *up) i->head = &up->list; spin_unlock_irq(&i->lock); irq_flags |= up->port.irqflags; +#ifdef CONFIG_SERIAL_8250_THREADED_IRQ + ret = request_threaded_irq(up->port.irq, serial8250_hard_irq, + serial8250_interrupt, irq_flags, up->port.name, i); +#else ret = request_irq(up->port.irq, serial8250_interrupt, irq_flags, up->port.name, i); +#endif if (ret < 0) serial_do_unlink(i, up); } diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index a5fe0e66c607..16e647473c4d 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1827,13 +1827,19 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) int serial8250_handle_irq(struct uart_port *port, unsigned int iir) { unsigned char status; +#ifndef CONFIG_SERIAL_8250_THREADED_IRQ unsigned long flags; +#endif struct uart_8250_port *up = up_to_u8250p(port); if (iir & UART_IIR_NO_INT) return 0; +#ifdef CONFIG_SERIAL_8250_THREADED_IRQ + spin_lock(&port->lock); +#else spin_lock_irqsave(&port->lock, flags); +#endif status = serial_port_in(port, UART_LSR); @@ -1845,7 +1851,11 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) if ((!up->dma || up->dma->tx_err) && (status & UART_LSR_THRE)) serial8250_tx_chars(up); +#ifdef CONFIG_SERIAL_8250_THREADED_IRQ + spin_unlock(&port->lock); +#else spin_unlock_irqrestore(&port->lock, flags); +#endif return 1; } EXPORT_SYMBOL_GPL(serial8250_handle_irq); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index a1161ec0256f..58a0f324cbea 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -202,6 +202,16 @@ config SERIAL_8250_MANY_PORTS say N here to save some memory. You can also say Y if you have an "intelligent" multiport card such as Cyclades, Digiboards, etc. +config SERIAL_8250_THREADED_IRQ + bool "Make serial 8250 interrupt processing threaded" + depends on SERIAL_8250 + help + Some virtual devices can work at very high speed (like QEMU KVM + serial 8250). So when burst happens this processing will capture + cpu. + Say Y if you want to make processing more friendly for others + processes. + # # Multi-port serial cards # -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html