2019-04-30 01:23:47

by Ji-Ze Hong (Peter Hong)

[permalink] [raw]
Subject: [PATCH V9 1/4] USB: serial: f81232: fix interrupt worker not stop

The F81232 will use interrupt worker to handle MSR change.
This patch will fix the issue that interrupt work should stop
in close() and suspend().

Cc: Johan Hovold <[email protected]>
Signed-off-by: Ji-Ze Hong (Peter Hong) <[email protected]>
---
v9:
1: change the sequence from patch index from 2 to 1.
2: using tty_port_initialized() to determinate port open state.

v8:
1: no change

v7:
1: first introduce to this series patch.

drivers/usb/serial/f81232.c | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)

diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
index 0dcdcb4b2cde..d43ec999bc5e 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -556,9 +556,12 @@ static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port)

static void f81232_close(struct usb_serial_port *port)
{
+ struct f81232_private *port_priv = usb_get_serial_port_data(port);
+
f81232_port_disable(port);
usb_serial_generic_close(port);
usb_kill_urb(port->interrupt_in_urb);
+ flush_work(&port_priv->interrupt_work);
}

static void f81232_dtr_rts(struct usb_serial_port *port, int on)
@@ -632,6 +635,40 @@ static int f81232_port_remove(struct usb_serial_port *port)
return 0;
}

+static int f81232_suspend(struct usb_serial *serial, pm_message_t message)
+{
+ struct usb_serial_port *port = serial->port[0];
+ struct f81232_private *port_priv = usb_get_serial_port_data(port);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
+ usb_kill_urb(port->read_urbs[i]);
+
+ usb_kill_urb(port->interrupt_in_urb);
+
+ if (port_priv)
+ flush_work(&port_priv->interrupt_work);
+
+ return 0;
+}
+
+static int f81232_resume(struct usb_serial *serial)
+{
+ struct usb_serial_port *port = serial->port[0];
+ int result;
+
+ if (tty_port_initialized(&port->port)) {
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
+ if (result) {
+ dev_err(&port->dev, "submit interrupt urb failed: %d",
+ result);
+ return result;
+ }
+ }
+
+ return usb_serial_generic_resume(serial);
+}
+
static struct usb_serial_driver f81232_device = {
.driver = {
.owner = THIS_MODULE,
@@ -655,6 +692,8 @@ static struct usb_serial_driver f81232_device = {
.read_int_callback = f81232_read_int_callback,
.port_probe = f81232_port_probe,
.port_remove = f81232_port_remove,
+ .suspend = f81232_suspend,
+ .resume = f81232_resume,
};

static struct usb_serial_driver * const serial_drivers[] = {
--
2.7.4


2019-04-30 01:24:00

by Ji-Ze Hong (Peter Hong)

[permalink] [raw]
Subject: [PATCH V9 4/4] USB: serial: f81232: implement break control

Implement Fintek F81232 break on/off with LCR register.
It's the same with 16550A LCR register layout.

Signed-off-by: Ji-Ze Hong (Peter Hong) <[email protected]>
---
v9:
1: no change

v8:
1: no change

v7:
1: no change

v6:
1: no change

v5:
1: no change

v4:
1: no change

v3:
1: using shadow_lcr to save LCR in f81232_break_ctl()

drivers/usb/serial/f81232.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
index 6a1e6a27ce16..562c9babd144 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -65,6 +65,7 @@ struct f81232_private {
struct mutex lock;
u8 modem_control;
u8 modem_status;
+ u8 shadow_lcr;
speed_t baud_base;
struct work_struct lsr_work;
struct work_struct interrupt_work;
@@ -377,13 +378,23 @@ static void f81232_process_read_urb(struct urb *urb)

static void f81232_break_ctl(struct tty_struct *tty, int break_state)
{
- /* FIXME - Stubbed out for now */
+ struct usb_serial_port *port = tty->driver_data;
+ struct f81232_private *priv = usb_get_serial_port_data(port);
+ int status;

- /*
- * break_state = -1 to turn on break, and 0 to turn off break
- * see drivers/char/tty_io.c to see it used.
- * last_set_data_urb_value NEVER has the break bit set in it.
- */
+ mutex_lock(&priv->lock);
+
+ if (break_state)
+ priv->shadow_lcr |= UART_LCR_SBC;
+ else
+ priv->shadow_lcr &= ~UART_LCR_SBC;
+
+ status = f81232_set_register(port, LINE_CONTROL_REGISTER,
+ priv->shadow_lcr);
+ if (status)
+ dev_err(&port->dev, "set break failed: %d\n", status);
+
+ mutex_unlock(&priv->lock);
}

static int f81232_find_clk(speed_t baudrate)
@@ -519,6 +530,7 @@ static int f81232_port_disable(struct usb_serial_port *port)
static void f81232_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
+ struct f81232_private *priv = usb_get_serial_port_data(port);
u8 new_lcr = 0;
int status = 0;
speed_t baudrate;
@@ -572,11 +584,16 @@ static void f81232_set_termios(struct tty_struct *tty,
break;
}

+ mutex_lock(&priv->lock);
+
+ new_lcr |= (priv->shadow_lcr & UART_LCR_SBC);
status = f81232_set_register(port, LINE_CONTROL_REGISTER, new_lcr);
if (status) {
dev_err(&port->dev, "%s failed to set LCR: %d\n",
__func__, status);
}
+
+ mutex_unlock(&priv->lock);
}

static int f81232_tiocmget(struct tty_struct *tty)
--
2.7.4

2019-04-30 01:24:19

by Ji-Ze Hong (Peter Hong)

[permalink] [raw]
Subject: [PATCH V9 2/4] USB: serial: f81232: clear overrun flag

The F81232 will report data and LSR with bulk like following format:
bulk-in data: [LSR(1Byte)+DATA(1Byte)][LSR(1Byte)+DATA(1Byte)]...

LSR will auto clear frame/parity/break error flag when reading by H/W,
but overrrun will only cleared when reading LSR. So this patch add a
worker to read LSR when overrun and flush the worker on close() &
suspend().

Cc: Oliver Neukum <[email protected]>
Signed-off-by: Ji-Ze Hong (Peter Hong) <[email protected]>
---
v9:
1: change the patch index from 1 to 2.

v8:
1: Fix usb_submit_urb() in f81232_resume() with GFP_NOIO, not
GFP_KERNEL.

v7:
1: Remove serial->suspending check
2: Add port priv is_port_open to save port open state. We'll
register interrupt-in urb in f81232_resume() when port is
opened.
3: Using usb_kill_urb for read/interrupt urb to ensure urb
stopped.

v6:
1: Add deferred_lsr_work_needed to re-trigger when f81232_resume()

v5:
1: Source code base revert to v3 and remove all v4 changes.
2: Add serial->suspending check in f81232_process_read_urb()
before schedule_work(&priv->lsr_work) to avoid race condition.

v4:
1: Add serial->suspending check in f81232_lsr_worker() to avoid
re-trigger
2: Add port_priv-lsr_work_resched to re-trigger LSR worker

v3:
1: Add flush_work(&port_priv->lsr_work) in f81232_suspend().

v2:
1: Add flush_work(&port_priv->lsr_work) in f81232_close().

drivers/usb/serial/f81232.c | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
index d43ec999bc5e..f0de20a818cd 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -41,12 +41,14 @@ MODULE_DEVICE_TABLE(usb, id_table);
#define FIFO_CONTROL_REGISTER (0x02 + SERIAL_BASE_ADDRESS)
#define LINE_CONTROL_REGISTER (0x03 + SERIAL_BASE_ADDRESS)
#define MODEM_CONTROL_REGISTER (0x04 + SERIAL_BASE_ADDRESS)
+#define LINE_STATUS_REGISTER (0x05 + SERIAL_BASE_ADDRESS)
#define MODEM_STATUS_REGISTER (0x06 + SERIAL_BASE_ADDRESS)

struct f81232_private {
struct mutex lock;
u8 modem_control;
u8 modem_status;
+ struct work_struct lsr_work;
struct work_struct interrupt_work;
struct usb_serial_port *port;
};
@@ -282,6 +284,7 @@ static void f81232_read_int_callback(struct urb *urb)
static void f81232_process_read_urb(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
+ struct f81232_private *priv = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
char tty_flag;
unsigned int i;
@@ -315,6 +318,7 @@ static void f81232_process_read_urb(struct urb *urb)

if (lsr & UART_LSR_OE) {
port->icount.overrun++;
+ schedule_work(&priv->lsr_work);
tty_insert_flip_char(&port->port, 0,
TTY_OVERRUN);
}
@@ -562,6 +566,7 @@ static void f81232_close(struct usb_serial_port *port)
usb_serial_generic_close(port);
usb_kill_urb(port->interrupt_in_urb);
flush_work(&port_priv->interrupt_work);
+ flush_work(&port_priv->lsr_work);
}

static void f81232_dtr_rts(struct usb_serial_port *port, int on)
@@ -606,6 +611,21 @@ static void f81232_interrupt_work(struct work_struct *work)
f81232_read_msr(priv->port);
}

+static void f81232_lsr_worker(struct work_struct *work)
+{
+ struct f81232_private *priv;
+ struct usb_serial_port *port;
+ int status;
+ u8 tmp;
+
+ priv = container_of(work, struct f81232_private, lsr_work);
+ port = priv->port;
+
+ status = f81232_get_register(port, LINE_STATUS_REGISTER, &tmp);
+ if (status)
+ dev_warn(&port->dev, "read LSR failed: %d\n", status);
+}
+
static int f81232_port_probe(struct usb_serial_port *port)
{
struct f81232_private *priv;
@@ -616,6 +636,7 @@ static int f81232_port_probe(struct usb_serial_port *port)

mutex_init(&priv->lock);
INIT_WORK(&priv->interrupt_work, f81232_interrupt_work);
+ INIT_WORK(&priv->lsr_work, f81232_lsr_worker);

usb_set_serial_port_data(port, priv);

@@ -646,8 +667,10 @@ static int f81232_suspend(struct usb_serial *serial, pm_message_t message)

usb_kill_urb(port->interrupt_in_urb);

- if (port_priv)
+ if (port_priv) {
flush_work(&port_priv->interrupt_work);
+ flush_work(&port_priv->lsr_work);
+ }

return 0;
}
--
2.7.4

2019-04-30 01:24:34

by Ji-Ze Hong (Peter Hong)

[permalink] [raw]
Subject: [PATCH V9 3/4] USB: serial: f81232: add high baud rate support

The F81232 had 4 clocksource 1.846/18.46/14.77/24MHz and baud rates
can be up to 1.5Mbits with 24MHz.

F81232 Clock registers (106h)

Bit1-0: Clock source selector
00: 1.846MHz.
01: 18.46MHz.
10: 24MHz.
11: 14.77MHz.

Signed-off-by: Ji-Ze Hong (Peter Hong) <[email protected]>
---
v9:
1: no change

v8:
1: no change

v7:
1: no change

v6:
1: no change

v5:
1: no change

v4:
1: no change

v3:
1: change the baud_base in f81232_get_serial_info()

drivers/usb/serial/f81232.c | 105 +++++++++++++++++++++++++++++++++++++++-----
1 file changed, 94 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
index f0de20a818cd..6a1e6a27ce16 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -28,7 +28,8 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);

/* Maximum baudrate for F81232 */
-#define F81232_MAX_BAUDRATE 115200
+#define F81232_MAX_BAUDRATE 1500000
+#define F81232_DEF_BAUDRATE 9600

/* USB Control EP parameter */
#define F81232_REGISTER_REQUEST 0xa0
@@ -44,18 +45,42 @@ MODULE_DEVICE_TABLE(usb, id_table);
#define LINE_STATUS_REGISTER (0x05 + SERIAL_BASE_ADDRESS)
#define MODEM_STATUS_REGISTER (0x06 + SERIAL_BASE_ADDRESS)

+/*
+ * F81232 Clock registers (106h)
+ *
+ * Bit1-0: Clock source selector
+ * 00: 1.846MHz.
+ * 01: 18.46MHz.
+ * 10: 24MHz.
+ * 11: 14.77MHz.
+ */
+#define F81232_CLK_REGISTER 0x106
+#define F81232_CLK_1_846_MHZ 0
+#define F81232_CLK_18_46_MHZ BIT(0)
+#define F81232_CLK_24_MHZ BIT(1)
+#define F81232_CLK_14_77_MHZ (BIT(1) | BIT(0))
+#define F81232_CLK_MASK GENMASK(1, 0)
+
struct f81232_private {
struct mutex lock;
u8 modem_control;
u8 modem_status;
+ speed_t baud_base;
struct work_struct lsr_work;
struct work_struct interrupt_work;
struct usb_serial_port *port;
};

-static int calc_baud_divisor(speed_t baudrate)
+static u32 const baudrate_table[] = { 115200, 921600, 1152000, 1500000 };
+static u8 const clock_table[] = { F81232_CLK_1_846_MHZ, F81232_CLK_14_77_MHZ,
+ F81232_CLK_18_46_MHZ, F81232_CLK_24_MHZ };
+
+static int calc_baud_divisor(speed_t baudrate, speed_t clockrate)
{
- return DIV_ROUND_CLOSEST(F81232_MAX_BAUDRATE, baudrate);
+ if (!baudrate)
+ return 0;
+
+ return DIV_ROUND_CLOSEST(clockrate, baudrate);
}

static int f81232_get_register(struct usb_serial_port *port, u16 reg, u8 *val)
@@ -129,6 +154,21 @@ static int f81232_set_register(struct usb_serial_port *port, u16 reg, u8 val)
return status;
}

+static int f81232_set_mask_register(struct usb_serial_port *port, u16 reg,
+ u8 mask, u8 val)
+{
+ int status;
+ u8 tmp;
+
+ status = f81232_get_register(port, reg, &tmp);
+ if (status)
+ return status;
+
+ tmp = (tmp & ~mask) | (val & mask);
+
+ return f81232_set_register(port, reg, tmp);
+}
+
static void f81232_read_msr(struct usb_serial_port *port)
{
int status;
@@ -346,13 +386,53 @@ static void f81232_break_ctl(struct tty_struct *tty, int break_state)
*/
}

-static void f81232_set_baudrate(struct usb_serial_port *port, speed_t baudrate)
+static int f81232_find_clk(speed_t baudrate)
+{
+ int idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(baudrate_table); ++idx) {
+ if (baudrate <= baudrate_table[idx] &&
+ baudrate_table[idx] % baudrate == 0)
+ return idx;
+ }
+
+ return -EINVAL;
+}
+
+static void f81232_set_baudrate(struct tty_struct *tty,
+ struct usb_serial_port *port, speed_t baudrate,
+ speed_t old_baudrate)
{
+ struct f81232_private *priv = usb_get_serial_port_data(port);
u8 lcr;
int divisor;
int status = 0;
+ int i;
+ int idx;
+ speed_t baud_list[] = {baudrate, old_baudrate, F81232_DEF_BAUDRATE};
+
+ for (i = 0; i < ARRAY_SIZE(baud_list); ++i) {
+ idx = f81232_find_clk(baud_list[i]);
+ if (idx >= 0) {
+ baudrate = baud_list[i];
+ tty_encode_baud_rate(tty, baudrate, baudrate);
+ break;
+ }
+ }
+
+ if (idx < 0)
+ return;

- divisor = calc_baud_divisor(baudrate);
+ priv->baud_base = baudrate_table[idx];
+ divisor = calc_baud_divisor(baudrate, priv->baud_base);
+
+ status = f81232_set_mask_register(port, F81232_CLK_REGISTER,
+ F81232_CLK_MASK, clock_table[idx]);
+ if (status) {
+ dev_err(&port->dev, "%s failed to set CLK_REG: %d\n",
+ __func__, status);
+ return;
+ }

status = f81232_get_register(port, LINE_CONTROL_REGISTER,
&lcr); /* get LCR */
@@ -442,6 +522,7 @@ static void f81232_set_termios(struct tty_struct *tty,
u8 new_lcr = 0;
int status = 0;
speed_t baudrate;
+ speed_t old_baud;

/* Don't change anything if nothing has changed */
if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios))
@@ -454,11 +535,12 @@ static void f81232_set_termios(struct tty_struct *tty,

baudrate = tty_get_baud_rate(tty);
if (baudrate > 0) {
- if (baudrate > F81232_MAX_BAUDRATE) {
- baudrate = F81232_MAX_BAUDRATE;
- tty_encode_baud_rate(tty, baudrate, baudrate);
- }
- f81232_set_baudrate(port, baudrate);
+ if (old_termios)
+ old_baud = tty_termios_baud_rate(old_termios);
+ else
+ old_baud = F81232_DEF_BAUDRATE;
+
+ f81232_set_baudrate(tty, port, baudrate, old_baud);
}

if (C_PARENB(tty)) {
@@ -595,11 +677,12 @@ static int f81232_get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct usb_serial_port *port = tty->driver_data;
+ struct f81232_private *priv = usb_get_serial_port_data(port);

ss->type = PORT_16550A;
ss->line = port->minor;
ss->port = port->port_number;
- ss->baud_base = F81232_MAX_BAUDRATE;
+ ss->baud_base = priv->baud_base;
return 0;
}

--
2.7.4

2019-05-03 07:01:01

by Johan Hovold

[permalink] [raw]
Subject: Re: [PATCH V9 1/4] USB: serial: f81232: fix interrupt worker not stop

On Tue, Apr 30, 2019 at 09:22:29AM +0800, Ji-Ze Hong (Peter Hong) wrote:
> The F81232 will use interrupt worker to handle MSR change.
> This patch will fix the issue that interrupt work should stop
> in close() and suspend().
>
> Cc: Johan Hovold <[email protected]>
> Signed-off-by: Ji-Ze Hong (Peter Hong) <[email protected]>

> +static int f81232_resume(struct usb_serial *serial)
> +{
> + struct usb_serial_port *port = serial->port[0];
> + int result;
> +
> + if (tty_port_initialized(&port->port)) {
> + result = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
> + if (result) {
> + dev_err(&port->dev, "submit interrupt urb failed: %d",
> + result);

I added the missing '\n' to the error message.

> + return result;
> + }
> + }
> +
> + return usb_serial_generic_resume(serial);
> +}

This also fixes the issue with interrupt events not being received
after a suspend cycle, so I added that to the commit message.

Johan

2019-05-03 07:05:09

by Johan Hovold

[permalink] [raw]
Subject: Re: [PATCH V9 4/4] USB: serial: f81232: implement break control

On Tue, Apr 30, 2019 at 09:22:32AM +0800, Ji-Ze Hong (Peter Hong) wrote:
> Implement Fintek F81232 break on/off with LCR register.
> It's the same with 16550A LCR register layout.
>
> Signed-off-by: Ji-Ze Hong (Peter Hong) <[email protected]>
> ---

> static void f81232_break_ctl(struct tty_struct *tty, int break_state)
> {
> - /* FIXME - Stubbed out for now */
> + struct usb_serial_port *port = tty->driver_data;
> + struct f81232_private *priv = usb_get_serial_port_data(port);
> + int status;
>
> - /*
> - * break_state = -1 to turn on break, and 0 to turn off break
> - * see drivers/char/tty_io.c to see it used.
> - * last_set_data_urb_value NEVER has the break bit set in it.
> - */
> + mutex_lock(&priv->lock);
> +
> + if (break_state)
> + priv->shadow_lcr |= UART_LCR_SBC;
> + else
> + priv->shadow_lcr &= ~UART_LCR_SBC;
> +
> + status = f81232_set_register(port, LINE_CONTROL_REGISTER,
> + priv->shadow_lcr);
> + if (status)
> + dev_err(&port->dev, "set break failed: %d\n", status);
> +
> + mutex_unlock(&priv->lock);
> }

> @@ -519,6 +530,7 @@ static int f81232_port_disable(struct usb_serial_port *port)
> static void f81232_set_termios(struct tty_struct *tty,
> struct usb_serial_port *port, struct ktermios *old_termios)
> {
> + struct f81232_private *priv = usb_get_serial_port_data(port);
> u8 new_lcr = 0;
> int status = 0;
> speed_t baudrate;
> @@ -572,11 +584,16 @@ static void f81232_set_termios(struct tty_struct *tty,
> break;
> }
>
> + mutex_lock(&priv->lock);
> +
> + new_lcr |= (priv->shadow_lcr & UART_LCR_SBC);
> status = f81232_set_register(port, LINE_CONTROL_REGISTER, new_lcr);
> if (status) {
> dev_err(&port->dev, "%s failed to set LCR: %d\n",
> __func__, status);
> }
> +
> + mutex_unlock(&priv->lock);

You forgot to update shadow_lcr here so the line settings would be
corrupted (e.g set to 5 bit words) whenever a break is signalled.

Did you not test this version of the patch?

I added the missing update, but please test the code that's in my
usb-next branch in a minute and confirm everything works as expected.

All four patches now applied.

Thanks,
Johan

2019-05-06 02:55:30

by Ji-Ze Hong (Peter Hong)

[permalink] [raw]
Subject: Re: [PATCH V9 4/4] USB: serial: f81232: implement break control

Hi Johan,

Johan Hovold 於 2019/5/3 下午 02:59 寫道:
>> @@ -519,6 +530,7 @@ static int f81232_port_disable(struct usb_serial_port *port)
>> static void f81232_set_termios(struct tty_struct *tty,
>> struct usb_serial_port *port, struct ktermios *old_termios)
>> {
>> + struct f81232_private *priv = usb_get_serial_port_data(port);
>> u8 new_lcr = 0;
>> int status = 0;
>> speed_t baudrate;
>> @@ -572,11 +584,16 @@ static void f81232_set_termios(struct tty_struct *tty,
>> break;
>> }
>>
>> + mutex_lock(&priv->lock);
>> +
>> + new_lcr |= (priv->shadow_lcr & UART_LCR_SBC);
>> status = f81232_set_register(port, LINE_CONTROL_REGISTER, new_lcr);
>> if (status) {
>> dev_err(&port->dev, "%s failed to set LCR: %d\n",
>> __func__, status);
>> }
>> +
>> + mutex_unlock(&priv->lock);
>
> You forgot to update shadow_lcr here so the line settings would be
> corrupted (e.g set to 5 bit words) whenever a break is signalled.
>
> Did you not test this version of the patch?
>
> I added the missing update, but please test the code that's in my
> usb-next branch in a minute and confirm everything works as expected.
>

Thanks for mention and patch the lost parts. I had only tested the
break signal and forgot to test full LCR. I'll add it to my test items
and it tested well on new usb-next branch after your fix.

BTW, Should I disable break control when port close ?

Thanks.

--
With Best Regards,
Peter Hong

2019-05-07 09:19:22

by Johan Hovold

[permalink] [raw]
Subject: Re: [PATCH V9 4/4] USB: serial: f81232: implement break control

On Mon, May 06, 2019 at 10:52:27AM +0800, Ji-Ze Hong (Peter Hong) wrote:

> > You forgot to update shadow_lcr here so the line settings would be
> > corrupted (e.g set to 5 bit words) whenever a break is signalled.
> >
> > Did you not test this version of the patch?
> >
> > I added the missing update, but please test the code that's in my
> > usb-next branch in a minute and confirm everything works as expected.
> >
>
> Thanks for mention and patch the lost parts. I had only tested the
> break signal and forgot to test full LCR. I'll add it to my test items
> and it tested well on new usb-next branch after your fix.

Thanks for confirming!

> BTW, Should I disable break control when port close ?

Yes, that would be good even if many tty drivers currently fail to do
so.

Johan