* [PATCH v1 1/4] usb: serial: mxuport: add support for more MXU50U UART devices
2026-03-24 3:50 [PATCH v1 0/4] usb: serial: mxuport: extend MXU50U support and runtime controls Crescent Hsieh
@ 2026-03-24 3:50 ` Crescent Hsieh
2026-03-24 3:50 ` [PATCH v1 2/4] usb: serial: mxuport: handle SEND_NEXT tx flow control Crescent Hsieh
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Crescent Hsieh @ 2026-03-24 3:50 UTC (permalink / raw)
To: Greg Kroah-Hartman, Johan Hovold; +Cc: linux-usb, linux-kernel, Crescent Hsieh
Add support for additional Moxa devices using the MXU50U UART family.
Extend the device ID table and port-count handling for 3-, 5-, 6- and
7-port devices, and update firmware selection to use the matching
MXU50U firmware images and version offsets.
Signed-off-by: Crescent Hsieh <crescentcy.hsieh@moxa.com>
---
drivers/usb/serial/mxuport.c | 132 +++++++++++++++++++++++++++++++----
1 file changed, 118 insertions(+), 14 deletions(-)
diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c
index ad5fdf55a02e..034b506322c2 100644
--- a/drivers/usb/serial/mxuport.c
+++ b/drivers/usb/serial/mxuport.c
@@ -39,6 +39,25 @@
#define MX_UPORT1613_PID 0x1613
#define MX_UPORT1653_PID 0x1653
+#define MX_UPORT1252_PID 0x1252
+#define MX_UPORT1253_PID 0x1253
+#define MX_UPORT1411_PID 0x1411
+#define MX_UPORT1452_PID 0x1452
+#define MX_UPORT1453_PID 0x1453
+#define MX_UPORT1619_PID 0x1619
+#define MX_UPORT1659_PID 0x1659
+#define MX_UPORT165A_PID 0x165A
+#define MX_UPORT165B_PID 0x165B
+
+#define MX_MU250U_PID 0x0250
+#define MX_MU450U_PID 0x0450
+#define MX_MU850U_PID 0x0850
+
+#define MX_MU850U_6PORT_PID 0x7002
+#define MX_MUX50U_3PORT_PID 0x7003
+#define MX_MU850U_5PORT_PID 0x7004
+#define MX_MU850U_7PORT_PID 0x7005
+
/* Definitions for USB info */
#define HEADER_SIZE 4
#define EVENT_LENGTH 8
@@ -48,6 +67,9 @@
#define VER_ADDR_1 0x20
#define VER_ADDR_2 0x24
#define VER_ADDR_3 0x28
+#define NEW_ADDR_1 0x86
+#define NEW_ADDR_2 0x88
+#define NEW_ADDR_3 0x8A
/* Definitions for USB vendor request */
#define RQ_VENDOR_NONE 0x00
@@ -147,9 +169,13 @@
#define MX_WAIT_FOR_SEND_NEXT 0x0080
#define MX_UPORT_2_PORT BIT(0)
-#define MX_UPORT_4_PORT BIT(1)
-#define MX_UPORT_8_PORT BIT(2)
-#define MX_UPORT_16_PORT BIT(3)
+#define MX_UPORT_3_PORT BIT(1)
+#define MX_UPORT_4_PORT BIT(2)
+#define MX_UPORT_5_PORT BIT(3)
+#define MX_UPORT_6_PORT BIT(4)
+#define MX_UPORT_7_PORT BIT(5)
+#define MX_UPORT_8_PORT BIT(6)
+#define MX_UPORT_16_PORT BIT(7)
/* This structure holds all of the local port information */
struct mxuport_port {
@@ -179,7 +205,39 @@ static const struct usb_device_id mxuport_idtable[] = {
.driver_info = MX_UPORT_16_PORT },
{ USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1653_PID),
.driver_info = MX_UPORT_16_PORT },
- {} /* Terminating entry */
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1252_PID),
+ .driver_info = MX_UPORT_2_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1253_PID),
+ .driver_info = MX_UPORT_2_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1411_PID),
+ .driver_info = MX_UPORT_4_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1452_PID),
+ .driver_info = MX_UPORT_4_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1453_PID),
+ .driver_info = MX_UPORT_4_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1619_PID),
+ .driver_info = MX_UPORT_8_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1659_PID),
+ .driver_info = MX_UPORT_8_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT165A_PID),
+ .driver_info = MX_UPORT_8_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT165B_PID),
+ .driver_info = MX_UPORT_8_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_MU250U_PID),
+ .driver_info = MX_UPORT_2_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_MU450U_PID),
+ .driver_info = MX_UPORT_4_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_MU850U_PID),
+ .driver_info = MX_UPORT_8_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_MU850U_6PORT_PID),
+ .driver_info = MX_UPORT_6_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_MUX50U_3PORT_PID),
+ .driver_info = MX_UPORT_3_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_MU850U_5PORT_PID),
+ .driver_info = MX_UPORT_5_PORT },
+ { USB_DEVICE(MX_USBSERIAL_VID, MX_MU850U_7PORT_PID),
+ .driver_info = MX_UPORT_7_PORT },
+ {} /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, mxuport_idtable);
@@ -944,8 +1002,16 @@ static int mxuport_calc_num_ports(struct usb_serial *serial,
if (features & MX_UPORT_2_PORT) {
num_ports = 2;
+ } else if (features & MX_UPORT_3_PORT) {
+ num_ports = 3;
} else if (features & MX_UPORT_4_PORT) {
num_ports = 4;
+ } else if (features & MX_UPORT_5_PORT) {
+ num_ports = 5;
+ } else if (features & MX_UPORT_6_PORT) {
+ num_ports = 6;
+ } else if (features & MX_UPORT_7_PORT) {
+ num_ports = 7;
} else if (features & MX_UPORT_8_PORT) {
num_ports = 8;
} else if (features & MX_UPORT_16_PORT) {
@@ -1053,6 +1119,7 @@ static int mxuport_probe(struct usb_serial *serial,
int local_ver;
char buf[32];
int err;
+ bool is_mux50u = false;
/* Load our firmware */
err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_QUERY_FW_CONFIG, 0, 0);
@@ -1065,12 +1132,41 @@ static int mxuport_probe(struct usb_serial *serial,
if (err < 0)
return err;
- dev_dbg(&serial->interface->dev, "Device firmware version v%x.%x.%x\n",
+ dev_dbg(&serial->interface->dev, "Device firmware version v%d.%d.%d\n",
(version & 0xff0000) >> 16,
(version & 0xff00) >> 8,
(version & 0xff));
- snprintf(buf, sizeof(buf) - 1, "moxa/moxa-%04x.fw", productid);
+ switch (productid) {
+ case MX_UPORT1252_PID:
+ case MX_UPORT1253_PID:
+ case MX_UPORT1411_PID:
+ case MX_UPORT1452_PID:
+ case MX_UPORT1453_PID:
+ case MX_UPORT1619_PID:
+ case MX_UPORT1659_PID:
+ case MX_UPORT165A_PID:
+ case MX_UPORT165B_PID:
+ is_mux50u = true;
+ snprintf(buf, sizeof(buf) - 1, "moxa/moxa-up-mux50u.fw");
+
+ break;
+ case MX_MU250U_PID:
+ case MX_MU450U_PID:
+ case MX_MU850U_PID:
+ case MX_MU850U_6PORT_PID:
+ case MX_MUX50U_3PORT_PID:
+ case MX_MU850U_5PORT_PID:
+ case MX_MU850U_7PORT_PID:
+ is_mux50u = true;
+ snprintf(buf, sizeof(buf) - 1, "moxa/moxa-pf-mux50u.fw");
+
+ break;
+ default:
+ snprintf(buf, sizeof(buf) - 1, "moxa/moxa-%04x.fw", productid);
+
+ break;
+ }
err = request_firmware(&fw_p, buf, &serial->interface->dev);
if (err) {
@@ -1080,14 +1176,22 @@ static int mxuport_probe(struct usb_serial *serial,
/* Use the firmware already in the device */
err = 0;
} else {
- local_ver = ((fw_p->data[VER_ADDR_1] << 16) |
- (fw_p->data[VER_ADDR_2] << 8) |
- fw_p->data[VER_ADDR_3]);
+ if (is_mux50u) {
+ local_ver = ((fw_p->data[NEW_ADDR_1] << 16) |
+ (fw_p->data[NEW_ADDR_2] << 8) |
+ (fw_p->data[NEW_ADDR_3]));
+ } else {
+ local_ver = ((fw_p->data[VER_ADDR_1] << 16) |
+ (fw_p->data[VER_ADDR_2] << 8) |
+ (fw_p->data[VER_ADDR_3]));
+ }
dev_dbg(&serial->interface->dev,
- "Available firmware version v%x.%x.%x\n",
- fw_p->data[VER_ADDR_1], fw_p->data[VER_ADDR_2],
- fw_p->data[VER_ADDR_3]);
- if (local_ver > version) {
+ "Available firmware version v%d.%d.%d\n",
+ (local_ver & 0xff0000) >> 16,
+ (local_ver & 0xff00) >> 8,
+ (local_ver & 0xff));
+
+ if (local_ver != version) {
err = mxuport_download_fw(serial, fw_p);
if (err)
goto out;
@@ -1098,7 +1202,7 @@ static int mxuport_probe(struct usb_serial *serial,
}
dev_info(&serial->interface->dev,
- "Using device firmware version v%x.%x.%x\n",
+ "Using device firmware version v%d.%d.%d\n",
(version & 0xff0000) >> 16,
(version & 0xff00) >> 8,
(version & 0xff));
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v1 2/4] usb: serial: mxuport: handle SEND_NEXT tx flow control
2026-03-24 3:50 [PATCH v1 0/4] usb: serial: mxuport: extend MXU50U support and runtime controls Crescent Hsieh
2026-03-24 3:50 ` [PATCH v1 1/4] usb: serial: mxuport: add support for more MXU50U UART devices Crescent Hsieh
@ 2026-03-24 3:50 ` Crescent Hsieh
2026-03-24 3:50 ` [PATCH v1 3/4] usb: serial: mxuport: support serial interface mode configuration Crescent Hsieh
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Crescent Hsieh @ 2026-03-24 3:50 UTC (permalink / raw)
To: Greg Kroah-Hartman, Johan Hovold; +Cc: linux-usb, linux-kernel, Crescent Hsieh
Track the transmitted payload size per port and stop queueing more data
once a bulk-out transfer reaches the device buffer threshold.
Resume transmission when the device reports UPORT_EVENT_SEND_NEXT, and
reset the TX flow-control state when the port is opened.
This prevents the driver from queueing more TX data until the device
reports that it is ready to accept the next transfer.
Signed-off-by: Crescent Hsieh <crescentcy.hsieh@moxa.com>
---
drivers/usb/serial/mxuport.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c
index 034b506322c2..4d29a431cefd 100644
--- a/drivers/usb/serial/mxuport.c
+++ b/drivers/usb/serial/mxuport.c
@@ -179,6 +179,8 @@
/* This structure holds all of the local port information */
struct mxuport_port {
+ u32 sent_payload;
+ u32 hold_reason;
u8 mcr_state; /* Last MCR state */
u8 msr_state; /* Last MSR state */
struct mutex mutex; /* Protects mcr_state */
@@ -250,9 +252,13 @@ MODULE_DEVICE_TABLE(usb, mxuport_idtable);
static int mxuport_prepare_write_buffer(struct usb_serial_port *port,
void *dest, size_t size)
{
+ struct mxuport_port *mxport = usb_get_serial_port_data(port);
u8 *buf = dest;
int count;
+ if (mxport->hold_reason & MX_WAIT_FOR_SEND_NEXT)
+ return 0;
+
count = kfifo_out_locked(&port->write_fifo, buf + HEADER_SIZE,
size - HEADER_SIZE,
&port->lock);
@@ -263,6 +269,13 @@ static int mxuport_prepare_write_buffer(struct usb_serial_port *port,
dev_dbg(&port->dev, "%s - size %zd count %d\n", __func__,
size, count);
+ mxport->sent_payload += count;
+
+ if (mxport->sent_payload >= port->bulk_out_size) {
+ mxport->hold_reason |= MX_WAIT_FOR_SEND_NEXT;
+ buf[0] |= 0x80;
+ }
+
return count + HEADER_SIZE;
}
@@ -484,6 +497,9 @@ static void mxuport_lsr_event(struct usb_serial_port *port, u8 buf[4])
static void mxuport_process_read_urb_event(struct usb_serial_port *port,
u8 buf[4], u32 event)
{
+ struct mxuport_port *mxport = usb_get_serial_port_data(port);
+ unsigned long flags;
+
dev_dbg(&port->dev, "%s - receive event : %04x\n", __func__, event);
switch (event) {
@@ -492,6 +508,13 @@ static void mxuport_process_read_urb_event(struct usb_serial_port *port,
* Sent as part of the flow control on device buffers.
* Not currently used.
*/
+ if (mxport->hold_reason & MX_WAIT_FOR_SEND_NEXT) {
+ spin_lock_irqsave(&mxport->spinlock, flags);
+ mxport->hold_reason &= ~MX_WAIT_FOR_SEND_NEXT;
+ mxport->sent_payload = 0;
+ usb_serial_generic_write_start(port, GFP_ATOMIC);
+ spin_unlock_irqrestore(&mxport->spinlock, flags);
+ }
break;
case UPORT_EVENT_MSR:
mxuport_msr_event(port, buf);
@@ -1318,6 +1341,9 @@ static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port)
* returns.
*/
mxport->msr_state = 0;
+ mxport->sent_payload = 0;
+ mxport->hold_reason = 0;
+ kfifo_reset(&port->write_fifo);
return err;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v1 3/4] usb: serial: mxuport: support serial interface mode configuration
2026-03-24 3:50 [PATCH v1 0/4] usb: serial: mxuport: extend MXU50U support and runtime controls Crescent Hsieh
2026-03-24 3:50 ` [PATCH v1 1/4] usb: serial: mxuport: add support for more MXU50U UART devices Crescent Hsieh
2026-03-24 3:50 ` [PATCH v1 2/4] usb: serial: mxuport: handle SEND_NEXT tx flow control Crescent Hsieh
@ 2026-03-24 3:50 ` Crescent Hsieh
2026-03-24 3:50 ` [PATCH v1 4/4] usb: serial: mxuport: add sysfs control for UART FIFO Crescent Hsieh
2026-03-30 7:24 ` [PATCH v1 0/4] usb: serial: mxuport: extend MXU50U support and runtime controls Crescent Hsieh
4 siblings, 0 replies; 7+ messages in thread
From: Crescent Hsieh @ 2026-03-24 3:50 UTC (permalink / raw)
To: Greg Kroah-Hartman, Johan Hovold; +Cc: linux-usb, linux-kernel, Crescent Hsieh
Add support for configuring the serial interface mode through
TIOCSRS485 and TIOCGRS485 using struct serial_rs485.
Sanitize the requested RS-485 settings and map them to the device
interface modes before issuing the vendor command to the firmware.
This allows userspace to switch between RS232, RS422, 2-wire RS485,
and 4-wire RS485, and to query the current per-port configuration.
Signed-off-by: Crescent Hsieh <crescentcy.hsieh@moxa.com>
---
drivers/usb/serial/mxuport.c | 86 ++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c
index 4d29a431cefd..9a8bb4f02da3 100644
--- a/drivers/usb/serial/mxuport.c
+++ b/drivers/usb/serial/mxuport.c
@@ -183,6 +183,7 @@ struct mxuport_port {
u32 hold_reason;
u8 mcr_state; /* Last MCR state */
u8 msr_state; /* Last MSR state */
+ struct serial_rs485 rs485;
struct mutex mutex; /* Protects mcr_state */
spinlock_t spinlock; /* Protects msr_state */
};
@@ -1348,6 +1349,90 @@ static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port)
return err;
}
+static void mxuport_sanitize_serial_rs485(struct serial_rs485 *rs485)
+{
+ if (!(rs485->flags & SER_RS485_ENABLED)) {
+ memset(rs485, 0, sizeof(*rs485));
+ return;
+ }
+ if (rs485->flags & SER_RS485_MODE_RS422) {
+ rs485->flags &= (SER_RS485_ENABLED | SER_RS485_MODE_RS422);
+ return;
+ }
+ rs485->flags &= (SER_RS485_ENABLED | SER_RS485_RX_DURING_TX);
+
+ memset(rs485->padding, 0, sizeof(rs485->padding));
+}
+
+static int mxuport_rs485_config(struct usb_serial_port *port,
+ struct serial_rs485 *rs485)
+{
+ struct usb_serial *serial = port->serial;
+ u16 mode = MX_INT_RS232;
+
+ if (rs485->flags & SER_RS485_ENABLED) {
+ if (rs485->flags & SER_RS485_MODE_RS422)
+ mode = MX_INT_RS422;
+ else if (rs485->flags & SER_RS485_RX_DURING_TX)
+ mode = MX_INT_4W_RS485;
+ else
+ mode = MX_INT_2W_RS485;
+ }
+
+ return mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_INTERFACE, mode,
+ port->port_number);
+}
+
+static int mxuport_get_rs485_config(struct usb_serial_port *port,
+ struct serial_rs485 __user *rs485)
+{
+ struct mxuport_port *mxport = usb_get_serial_port_data(port);
+
+ if (copy_to_user(rs485, &mxport->rs485, sizeof(mxport->rs485)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int mxuport_set_rs485_config(struct usb_serial_port *port,
+ struct serial_rs485 __user *rs485_user)
+{
+ struct mxuport_port *mxport = usb_get_serial_port_data(port);
+ struct serial_rs485 rs485;
+ int ret;
+
+ if (copy_from_user(&rs485, rs485_user, sizeof(*rs485_user)))
+ return -EFAULT;
+
+ mxuport_sanitize_serial_rs485(&rs485);
+
+ ret = mxuport_rs485_config(port, &rs485);
+ if (!ret)
+ mxport->rs485 = rs485;
+
+ if (copy_to_user(rs485_user, &mxport->rs485, sizeof(mxport->rs485)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int mxuport_ioctl(struct tty_struct *tty,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ void __user *uarg = (void __user *)arg;
+
+ switch (cmd) {
+ case TIOCGRS485:
+ return mxuport_get_rs485_config(port, uarg);
+ case TIOCSRS485:
+ return mxuport_set_rs485_config(port, uarg);
+ }
+
+ return -ENOIOCTLCMD;
+}
+
static void mxuport_close(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
@@ -1421,6 +1506,7 @@ static struct usb_serial_driver mxuport_device = {
.calc_num_ports = mxuport_calc_num_ports,
.open = mxuport_open,
.close = mxuport_close,
+ .ioctl = mxuport_ioctl,
.set_termios = mxuport_set_termios,
.break_ctl = mxuport_break_ctl,
.tx_empty = mxuport_tx_empty,
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v1 4/4] usb: serial: mxuport: add sysfs control for UART FIFO
2026-03-24 3:50 [PATCH v1 0/4] usb: serial: mxuport: extend MXU50U support and runtime controls Crescent Hsieh
` (2 preceding siblings ...)
2026-03-24 3:50 ` [PATCH v1 3/4] usb: serial: mxuport: support serial interface mode configuration Crescent Hsieh
@ 2026-03-24 3:50 ` Crescent Hsieh
2026-03-30 7:24 ` [PATCH v1 0/4] usb: serial: mxuport: extend MXU50U support and runtime controls Crescent Hsieh
4 siblings, 0 replies; 7+ messages in thread
From: Crescent Hsieh @ 2026-03-24 3:50 UTC (permalink / raw)
To: Greg Kroah-Hartman, Johan Hovold; +Cc: linux-usb, linux-kernel, Crescent Hsieh
Add a per-port sysfs attribute, uart_fifo, to allow userspace to enable
or disable the UART FIFO at runtime.
Map the requested state to the RQ_VENDOR_SET_FIFO_DISABLE vendor command
and track the current FIFO setting in the per-port private data.
Initialize the FIFO state during port probe and remove the sysfs
attribute when the port is released.
Signed-off-by: Crescent Hsieh <crescentcy.hsieh@moxa.com>
---
drivers/usb/serial/mxuport.c | 75 ++++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c
index 9a8bb4f02da3..24b86d1a31d4 100644
--- a/drivers/usb/serial/mxuport.c
+++ b/drivers/usb/serial/mxuport.c
@@ -183,6 +183,7 @@ struct mxuport_port {
u32 hold_reason;
u8 mcr_state; /* Last MCR state */
u8 msr_state; /* Last MSR state */
+ bool fifo_enabled;
struct serial_rs485 rs485;
struct mutex mutex; /* Protects mcr_state */
spinlock_t spinlock; /* Protects msr_state */
@@ -1242,6 +1243,68 @@ static int mxuport_probe(struct usb_serial *serial,
return err;
}
+static ssize_t uart_fifo_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct usb_serial_port *port = to_usb_serial_port(dev);
+ struct mxuport_port *mxport = usb_get_serial_port_data(port);
+
+ if (mxport->fifo_enabled)
+ return sysfs_emit(buf, "enabled\n");
+
+ return sysfs_emit(buf, "disabled\n");
+}
+
+static ssize_t uart_fifo_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct usb_serial_port *port = to_usb_serial_port(dev);
+ struct mxuport_port *mxport = usb_get_serial_port_data(port);
+ struct usb_serial *serial = port->serial;
+ bool state;
+ int ret;
+
+ if (!count)
+ return -EINVAL;
+
+ ret = kstrtobool(buf, &state);
+ if (ret < 0)
+ return ret;
+
+ if (state == 1) {
+ ret = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_FIFO_DISABLE,
+ 0, port->port_number);
+ if (ret)
+ return ret;
+
+ mxport->fifo_enabled = true;
+ } else if (state == 0) {
+ ret = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_FIFO_DISABLE,
+ 1, port->port_number);
+ if (ret)
+ return ret;
+
+ mxport->fifo_enabled = false;
+ } else {
+ return -EINVAL;
+ }
+
+ return count;
+}
+static DEVICE_ATTR_RW(uart_fifo);
+
+static int mxuport_create_sysfs_attrs(struct usb_serial_port *port)
+{
+ return device_create_file(&port->dev, &dev_attr_uart_fifo);
+}
+
+static int mxuport_remove_sysfs_attrs(struct usb_serial_port *port)
+{
+ device_remove_file(&port->dev, &dev_attr_uart_fifo);
+
+ return 0;
+}
static int mxuport_port_probe(struct usb_serial_port *port)
{
@@ -1266,18 +1329,29 @@ static int mxuport_port_probe(struct usb_serial_port *port)
if (err)
return err;
+ mxport->fifo_enabled = true;
+
/* Set transmission mode (Hi-Performance) */
err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_HIGH_PERFOR,
0, port->port_number);
if (err)
return err;
+ err = mxuport_create_sysfs_attrs(port);
+ if (err)
+ return err;
+
/* Set interface (RS-232) */
return mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_INTERFACE,
MX_INT_RS232,
port->port_number);
}
+static void mxuport_port_remove(struct usb_serial_port *port)
+{
+ mxuport_remove_sysfs_attrs(port);
+}
+
static int mxuport_attach(struct usb_serial *serial)
{
struct usb_serial_port *port0 = serial->port[0];
@@ -1501,6 +1575,7 @@ static struct usb_serial_driver mxuport_device = {
.num_bulk_out = 1,
.probe = mxuport_probe,
.port_probe = mxuport_port_probe,
+ .port_remove = mxuport_port_remove,
.attach = mxuport_attach,
.release = mxuport_release,
.calc_num_ports = mxuport_calc_num_ports,
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v1 0/4] usb: serial: mxuport: extend MXU50U support and runtime controls
2026-03-24 3:50 [PATCH v1 0/4] usb: serial: mxuport: extend MXU50U support and runtime controls Crescent Hsieh
` (3 preceding siblings ...)
2026-03-24 3:50 ` [PATCH v1 4/4] usb: serial: mxuport: add sysfs control for UART FIFO Crescent Hsieh
@ 2026-03-30 7:24 ` Crescent Hsieh
2026-03-30 7:54 ` Johan Hovold
4 siblings, 1 reply; 7+ messages in thread
From: Crescent Hsieh @ 2026-03-30 7:24 UTC (permalink / raw)
To: Greg Kroah-Hartman, Johan Hovold; +Cc: linux-usb, linux-kernel
Hi,
Gentle ping on this series.
Please let me know if I should revise or split anything.
Related firmware patch:
https://lore.kernel.org/all/20260324024635.349522-1-crescentcy.hsieh@moxa.com/
Thanks,
Crescent Hsieh
^ permalink raw reply [flat|nested] 7+ messages in thread