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

serial: max310x: improve interrupt handling

When there is a heavy load of receiving characters to all
four UART's, the warning 'Hardware RX FIFO overrun' is
sometimes detected.
The current implementation always service first the highest UART
until no more interrupt and then service another UART
(ex: UART3 will be serviced for as long as there are interrupts
for it, then UART2, etc).

This commit handle all individual interrupt sources before
reading the global IRQ register again.

This commit has also a nice side-effect of improving the efficiency
of the driver by reducing the number of reads of the global
IRQ register.

Signed-off-by: Tapio Reijonen <tapio.reijonen@vaisala.com>
Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
Reviewed-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Link: https://lore.kernel.org/r/20250908-master-max310x-improve-interrupt-handling-v3-1-91985e82ba39@vaisala.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Tapio Reijonen and committed by
Greg Kroah-Hartman
8d17dc05 fc702e7d

+17 -6
+17 -6
drivers/tty/serial/max310x.c
··· 823 823 bool handled = false; 824 824 825 825 if (s->devtype->nr > 1) { 826 + bool done; 827 + 826 828 do { 827 829 unsigned int val = ~0; 830 + unsigned long irq; 831 + unsigned int port; 832 + 833 + done = true; 828 834 829 835 WARN_ON_ONCE(regmap_read(s->regmap, 830 836 MAX310X_GLOBALIRQ_REG, &val)); 831 - val = ((1 << s->devtype->nr) - 1) & ~val; 832 - if (!val) 833 - break; 834 - if (max310x_port_irq(s, fls(val) - 1) == IRQ_HANDLED) 835 - handled = true; 836 - } while (1); 837 + 838 + irq = val; 839 + 840 + for_each_clear_bit(port, &irq, s->devtype->nr) { 841 + done = false; 842 + 843 + if (max310x_port_irq(s, port) == IRQ_HANDLED) 844 + handled = true; 845 + } 846 + 847 + } while (!done); 837 848 } else { 838 849 if (max310x_port_irq(s, 0) == IRQ_HANDLED) 839 850 handled = true;