From: Crescent Hsieh <crescentcy.hsieh@moxa.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Jiri Slaby <jirislaby@kernel.org>,
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org,
FangpingFP.Cheng@moxa.com, Epson.Chiang@moxa.com,
Crescent Hsieh <crescentcy.hsieh@moxa.com>
Subject: [PATCH v2 10/15] serial: 8250_mxpcie: defer uart_write_wakeup() to workqueue
Date: Wed, 1 Jul 2026 11:41:23 +0800 [thread overview]
Message-ID: <20260701034128.218569-11-crescentcy.hsieh@moxa.com> (raw)
In-Reply-To: <20260701034128.218569-1-crescentcy.hsieh@moxa.com>
Avoid calling uart_write_wakeup() directly from the interrupt-driven TX
path.
Defer the wakeup to a per-port work item and coalesce multiple TX events
using a pending flag, so only one wakeup is scheduled while a previous
one is still outstanding.
Signed-off-by: Crescent Hsieh <crescentcy.hsieh@moxa.com>
---
drivers/tty/serial/8250/8250_mxpcie.c | 34 +++++++++++++++++++++++----
1 file changed, 29 insertions(+), 5 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_mxpcie.c b/drivers/tty/serial/8250/8250_mxpcie.c
index 63885348c14c..f8b7abd7871b 100644
--- a/drivers/tty/serial/8250/8250_mxpcie.c
+++ b/drivers/tty/serial/8250/8250_mxpcie.c
@@ -15,6 +15,7 @@
#include <linux/pci.h>
#include <linux/tty_flip.h>
#include <linux/types.h>
+#include <linux/workqueue.h>
#include <linux/8250_pci.h>
#include <linux/serial_8250.h>
@@ -104,7 +105,12 @@
#define MOXA_EVEN_RS_MASK GENMASK(3, 0)
#define MOXA_ODD_RS_MASK GENMASK(7, 4)
+#define MOXA_EVENT_TXLOW BIT(0)
+
struct mxpcie8250_port {
+ struct uart_port *port;
+ struct work_struct work;
+ unsigned long event_flags;
int line;
};
@@ -328,6 +334,8 @@ static void mxpcie8250_tx_chars(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
struct tty_port *tport = &port->state->port;
+ struct device *dev = port->dev;
+ struct mxpcie8250 *priv = dev_get_drvdata(dev);
unsigned int i, count, txsize;
unsigned char c;
@@ -348,9 +356,10 @@ static void mxpcie8250_tx_chars(struct uart_8250_port *up)
serial_out(up, MOXA_PUART_TX_FIFO_MEM + i, c);
}
- if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
+ if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) {
+ if (!test_and_set_bit(MOXA_EVENT_TXLOW, &priv->port[port->port_id].event_flags))
+ schedule_work(&priv->port[port->port_id].work);
+ }
if (kfifo_is_empty(&tport->xmit_fifo) && !(up->capabilities & UART_CAP_RPM))
port->ops->stop_tx(port);
}
@@ -382,6 +391,14 @@ static int mxpcie8250_handle_irq(struct uart_port *port)
return 1;
}
+static void mxpcie8250_work_handler(struct work_struct *work)
+{
+ struct mxpcie8250_port *priv_port = container_of(work, struct mxpcie8250_port, work);
+
+ if (test_and_clear_bit(MOXA_EVENT_TXLOW, &priv_port->event_flags))
+ uart_write_wakeup(priv_port->port);
+}
+
static void mxpcie8250_init_board(struct pci_dev *pdev, struct mxpcie8250 *priv)
{
void __iomem *bar2_base = priv->bar2_base;
@@ -437,7 +454,7 @@ static void mxpcie8250_setup_port(struct pci_dev *pdev,
static int mxpcie8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct device *dev = &pdev->dev;
- struct uart_8250_port up = {};
+ struct uart_8250_port up = {}, *new_port;
struct mxpcie8250 *priv;
unsigned short device = pdev->device;
unsigned int num_ports;
@@ -497,6 +514,11 @@ static int mxpcie8250_probe(struct pci_dev *pdev, const struct pci_device_id *id
up.port.iotype, priv->port[i].line);
break;
}
+ new_port = serial8250_get_port(priv->port[i].line);
+
+ priv->port[i].port = &new_port->port;
+
+ INIT_WORK(&priv->port[i].work, mxpcie8250_work_handler);
}
pci_set_drvdata(pdev, priv);
@@ -507,8 +529,10 @@ static void mxpcie8250_remove(struct pci_dev *pdev)
{
struct mxpcie8250 *priv = pci_get_drvdata(pdev);
- for (unsigned int i = 0; i < priv->num_ports; i++)
+ for (unsigned int i = 0; i < priv->num_ports; i++) {
+ cancel_work_sync(&priv->port[i].work);
serial8250_unregister_port(priv->port[i].line);
+ }
}
static const struct pci_device_id mxpcie8250_pci_ids[] = {
--
2.45.2
next prev parent reply other threads:[~2026-07-01 3:44 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-01 3:41 [PATCH v2 00/15] serial: 8250: add Moxa MUEx50 PCIe board support Crescent Hsieh
2026-07-01 3:41 ` [PATCH v2 01/15] serial: 8250: split Moxa PCIe serial board support out of 8250_pci Crescent Hsieh
2026-07-01 12:42 ` Andy Shevchenko
2026-07-01 3:41 ` [PATCH v2 02/15] serial: 8250: add Moxa MUEx50 UART port type Crescent Hsieh
2026-07-01 3:41 ` [PATCH v2 03/15] serial: 8250_mxpcie: enable enhanced mode and program FIFO trigger levels Crescent Hsieh
2026-07-01 3:41 ` [PATCH v2 04/15] serial: 8250_mxpcie: enable automatic RTS/CTS flow control Crescent Hsieh
2026-07-01 3:41 ` [PATCH v2 05/15] serial: 8250_mxpcie: offload XON/XOFF flow control to MUEx50 hardware Crescent Hsieh
2026-07-01 3:41 ` [PATCH v2 06/15] serial: 8250_mxpcie: add custom handle_irq callback Crescent Hsieh
2026-07-01 12:41 ` Andy Shevchenko
2026-07-01 3:41 ` [PATCH v2 07/15] serial: 8250_mxpcie: speed up RX using memory-mapped FIFO window Crescent Hsieh
2026-07-01 3:41 ` [PATCH v2 08/15] serial: 8250_mxpcie: speed up TX " Crescent Hsieh
2026-07-01 12:36 ` Andy Shevchenko
2026-07-01 3:41 ` [PATCH v2 09/15] serial: 8250_mxpcie: introduce per-port private data structure Crescent Hsieh
2026-07-01 3:41 ` Crescent Hsieh [this message]
2026-07-01 3:41 ` [PATCH v2 11/15] serial: 8250_mxpcie: support serial interface mode switching Crescent Hsieh
2026-07-01 3:41 ` [PATCH v2 12/15] serial: 8250: allow low-level drivers to override break control Crescent Hsieh
2026-07-01 3:41 ` [PATCH v2 13/15] serial: 8250_mxpcie: add break support for RS485 using MUEx50 features Crescent Hsieh
2026-07-01 3:41 ` [PATCH v2 14/15] serial: 8250: allow UART drivers to override rx_trig_bytes handling Crescent Hsieh
2026-07-01 3:41 ` [PATCH v2 15/15] serial: 8250_mxpcie: implement rx_trig_bytes callbacks via MUEx50 RTL Crescent Hsieh
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260701034128.218569-11-crescentcy.hsieh@moxa.com \
--to=crescentcy.hsieh@moxa.com \
--cc=Epson.Chiang@moxa.com \
--cc=FangpingFP.Cheng@moxa.com \
--cc=andriy.shevchenko@linux.intel.com \
--cc=gregkh@linuxfoundation.org \
--cc=jirislaby@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-serial@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox