[PATCH 2/4] serial: sh-sci: Don’t disable TX on TEI while the xmit kfifo still holds data
From: Biju
Date: Mon Oct 19 2026 - 14:30:29 EST
From: Biju Das <biju.das.jz@xxxxxxxxxxxxxx>
sci_tx_end_interrupt() handles the transmit-end interrupt (TEI) on
SCI and RSCI ports by clearing TE and TEIE, which turns the
transmitter off. It does this unconditionally, even if the xmit kfifo
was refilled after the last byte was written to the data register and
before TEI fired. The queued data is then not sent until the
transmitter is re-enabled, so output stalls or is lost.
Check whether the xmit kfifo is empty before shutting the transmitter
down. If data is still queued, clear TEIE, set TIE and hand over to
sci_tx_interrupt() so transmission continues normally. The existing
TE/TEIE teardown path only runs once the kfifo is drained.
To keep the handler independent of the register layout, add tie and
teie masks to struct sci_port_params_bits and populate them for the
SCI, SCIF and RSCI variants.
Fixes: d61ae331d6f3 ("tty: serial: sh-sci: Add support for tx end interrupt handling")
Signed-off-by: Biju Das <biju.das.jz@xxxxxxxxxxxxxx>
---
drivers/tty/serial/rsci.c | 2 ++
drivers/tty/serial/sh-sci-common.h | 2 ++
drivers/tty/serial/sh-sci.c | 22 ++++++++++++++++++----
3 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/serial/rsci.c b/drivers/tty/serial/rsci.c
index 40db9daa4272..52638db7bbeb 100644
--- a/drivers/tty/serial/rsci.c
+++ b/drivers/tty/serial/rsci.c
@@ -627,6 +627,8 @@ static const struct sci_port_params_bits rsci_port_param_bits = {
.rxtx_enable = CCR0_RE | CCR0_TE,
.te_clear = CCR0_TE | CCR0_TEIE,
.poll_sent_bits = CSR_TDRE | CSR_TEND,
+ .tie = CCR0_TIE,
+ .teie = CCR0_TEIE,
};
static const struct sci_port_params rsci_rzg3e_port_params = {
diff --git a/drivers/tty/serial/sh-sci-common.h b/drivers/tty/serial/sh-sci-common.h
index 01ff9fced803..273856fbc20b 100644
--- a/drivers/tty/serial/sh-sci-common.h
+++ b/drivers/tty/serial/sh-sci-common.h
@@ -56,6 +56,8 @@ struct sci_port_params_bits {
unsigned int rxtx_enable;
unsigned int te_clear;
unsigned int poll_sent_bits;
+ unsigned int tie;
+ unsigned int teie;
};
struct sci_common_regs {
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 9eb297dbc901..d577f9de6259 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -261,13 +261,17 @@ static bool sci_uart_earlycon_dev_probing;
static const struct sci_port_params_bits sci_sci_port_params_bits = {
.rxtx_enable = SCSCR_RE | SCSCR_TE,
.te_clear = SCSCR_TE | SCSCR_TEIE,
- .poll_sent_bits = SCI_TDRE | SCI_TEND
+ .poll_sent_bits = SCI_TDRE | SCI_TEND,
+ .tie = SCSCR_TIE,
+ .teie = SCSCR_TEIE
};
static const struct sci_port_params_bits sci_scif_port_params_bits = {
.rxtx_enable = SCSCR_RE | SCSCR_TE,
.te_clear = SCSCR_TE | SCSCR_TEIE,
- .poll_sent_bits = SCIF_TDFE | SCIF_TEND
+ .poll_sent_bits = SCIF_TDFE | SCIF_TEND,
+ .tie = SCSCR_TIE,
+ .teie = SCSCR_TEIE
};
static const struct sci_common_regs sci_common_regs = {
@@ -2012,6 +2016,7 @@ static irqreturn_t sci_tx_end_interrupt(int irq, void *ptr)
{
struct uart_port *port = ptr;
struct sci_port *s = to_sci_port(port);
+ struct tty_port *tport = &port->state->port;
const struct sci_common_regs *regs = s->params->common_regs;
unsigned long flags;
u32 ctrl;
@@ -2019,9 +2024,18 @@ static irqreturn_t sci_tx_end_interrupt(int irq, void *ptr)
if (s->type != PORT_SCI && !sci_is_rsci_type(s->type))
return sci_tx_interrupt(irq, ptr);
+ ctrl = s->ops->read_reg(port, regs->control);
+ if (!kfifo_is_empty(&tport->xmit_fifo)) {
+ uart_port_lock_irqsave(port, &flags);
+ ctrl &= ~(s->params->param_bits->teie);
+ ctrl |= s->params->param_bits->tie;
+ s->ops->write_reg(port, regs->control, ctrl);
+ uart_port_unlock_irqrestore(port, flags);
+ return sci_tx_interrupt(irq, ptr);
+ }
+
uart_port_lock_irqsave(port, &flags);
- ctrl = s->ops->read_reg(port, regs->control) &
- ~(s->params->param_bits->te_clear);
+ ctrl &= ~(s->params->param_bits->te_clear);
s->ops->write_reg(port, regs->control, ctrl);
uart_port_unlock_irqrestore(port, flags);
--
2.43.0