Skip to content

Commit fce3c5c

Browse files
tpetazzonigregkh
authored andcommitted
serial: max310x: rework RX interrupt handling
Currently, the RX interrupt logic uses the RXEMPTY interrupt, with the RXEMPTYINV bit set, which means we get an RX interrupt as soon as the RX FIFO is non-empty. However, with the MAX310X having a FIFO of 128 bytes, this makes very poor use of the FIFO: we trigger an interrupt as soon as the RX FIFO has one byte, which means a lot of interrupts, each only collecting a few bytes from the FIFO, causing a significant CPU load. Instead this commit relies on two other RX interrupt events: - MAX310X_IRQ_RXFIFO_BIT, which triggers when the RX FIFO has reached a certain threshold, which we define to be half of the FIFO size. This ensure we get an interrupt before the RX FIFO fills up. - MAX310X_LSR_RXTO_BIT, which triggers when the RX FIFO has received some bytes, and then no more bytes are received for a certain time. Arbitrarily, this time is defined to the time is takes to receive 4 characters. On a Microchip SAMA5D3 platform that is receiving 20 bytes every 16ms over one MAX310X UART, this patch has allowed to reduce the CPU consumption of the interrupt handler thread from ~25% to 6-7%. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com> Link: https://lore.kernel.org/r/20201001074415.349739-1-thomas.petazzoni@bootlin.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 85985a3 commit fce3c5c

File tree

1 file changed

+24
-5
lines changed

1 file changed

+24
-5
lines changed

Diff for: drivers/tty/serial/max310x.c

+24-5
Original file line numberDiff line numberDiff line change
@@ -1056,9 +1056,9 @@ static int max310x_startup(struct uart_port *port)
10561056
max310x_port_update(port, MAX310X_MODE1_REG,
10571057
MAX310X_MODE1_TRNSCVCTRL_BIT, 0);
10581058

1059-
/* Configure MODE2 register & Reset FIFOs*/
1060-
val = MAX310X_MODE2_RXEMPTINV_BIT | MAX310X_MODE2_FIFORST_BIT;
1061-
max310x_port_write(port, MAX310X_MODE2_REG, val);
1059+
/* Reset FIFOs */
1060+
max310x_port_write(port, MAX310X_MODE2_REG,
1061+
MAX310X_MODE2_FIFORST_BIT);
10621062
max310x_port_update(port, MAX310X_MODE2_REG,
10631063
MAX310X_MODE2_FIFORST_BIT, 0);
10641064

@@ -1086,8 +1086,27 @@ static int max310x_startup(struct uart_port *port)
10861086
/* Clear IRQ status register */
10871087
max310x_port_read(port, MAX310X_IRQSTS_REG);
10881088

1089-
/* Enable RX, TX, CTS change interrupts */
1090-
val = MAX310X_IRQ_RXEMPTY_BIT | MAX310X_IRQ_TXEMPTY_BIT;
1089+
/*
1090+
* Let's ask for an interrupt after a timeout equivalent to
1091+
* the receiving time of 4 characters after the last character
1092+
* has been received.
1093+
*/
1094+
max310x_port_write(port, MAX310X_RXTO_REG, 4);
1095+
1096+
/*
1097+
* Make sure we also get RX interrupts when the RX FIFO is
1098+
* filling up quickly, so get an interrupt when half of the RX
1099+
* FIFO has been filled in.
1100+
*/
1101+
max310x_port_write(port, MAX310X_FIFOTRIGLVL_REG,
1102+
MAX310X_FIFOTRIGLVL_RX(MAX310X_FIFO_SIZE / 2));
1103+
1104+
/* Enable RX timeout interrupt in LSR */
1105+
max310x_port_write(port, MAX310X_LSR_IRQEN_REG,
1106+
MAX310X_LSR_RXTO_BIT);
1107+
1108+
/* Enable LSR, RX FIFO trigger, CTS change interrupts */
1109+
val = MAX310X_IRQ_LSR_BIT | MAX310X_IRQ_RXFIFO_BIT | MAX310X_IRQ_TXEMPTY_BIT;
10911110
max310x_port_write(port, MAX310X_IRQEN_REG, val | MAX310X_IRQ_CTS_BIT);
10921111

10931112
return 0;

0 commit comments

Comments
 (0)