Am 01.11.2013 13:19, schrieb Mika Westerberg: > On Fri, Nov 01, 2013 at 12:49:22PM +0100, Frank Schäfer wrote: >> Some PL2303 chips are reported to lose bytes if the serial settings are set to >> the same values as before. >> At least HXD chips are affected, HX chips seem to be ok. >> The current code tries to avoid this by calling tty_termios_hw_change(), but >> this check isn't sufficient because different requested baud rates can result >> in identic encoded baud rates. >> The solution is to save and compare the encoded settings instead. > I tried this on top of rc7 and I can still see data get corrupted (both > 115200 and 460800 bps). Ok... Ready for the next round ? ;) Attached are two further experimental patches. Regards, Frank
>From 95a3f0e0751dad4ae39fdd7a915a2fa22997a540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Sch=C3=A4fer?= <fschaefer.oss@xxxxxxxxxxxxxx> Date: Fri, 1 Nov 2013 13:56:53 +0100 Subject: [PATCH] EXPERIMENTAL PATCH 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Frank Schäfer <fschaefer.oss@xxxxxxxxxxxxxx> --- drivers/usb/serial/pl2303.c | 30 ++++++++++++++++++------------ 1 Datei geändert, 18 Zeilen hinzugefügt(+), 12 Zeilen entfernt(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index bedf8e4..8496eef 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -496,20 +496,13 @@ static void pl2303_set_termios(struct tty_struct *tty, struct pl2303_serial_private *spriv = usb_get_serial_data(serial); struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; - unsigned char *buf; + unsigned char *buf, *buf_old; int i; u8 control; - /* - * The PL2303 is reported to lose bytes if you change serial settings - * even to the same values as before. Thus we actually need to filter - * in this specific case. - */ - if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios)) - return; - buf = kzalloc(7, GFP_KERNEL); - if (!buf) { + buf_old = kzalloc(7, GFP_KERNEL); + if (!buf || buf_old) { dev_err(&port->dev, "%s - out of memory.\n", __func__); /* Report back no change occurred */ if (old_termios) @@ -519,8 +512,8 @@ static void pl2303_set_termios(struct tty_struct *tty, i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, - 0, 0, buf, 7, 100); - dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); + 0, 0, buf_old, 7, 100); + dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf_old); if (C_CSIZE(tty)) { switch (C_CSIZE(tty)) { @@ -591,6 +584,17 @@ static void pl2303_set_termios(struct tty_struct *tty, dev_dbg(&port->dev, "parity = none\n"); } + /* + * Some PL2303 chips are reported to lose bytes if you change the + * serial settings even to the same values as before. + * At least HXD chips are affected, HX chips seem to be ok. + * Thus we actually need to filter in this specific case. + * NOTE: a tty_termios_hw_change() check isn't sufficient, because + * different baud rates can result in identic encoded values. + */ + if (!memcmp(buf, buf_old, 7)) + goto out; + i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, 0, 0, buf, 7, 100); @@ -626,7 +630,9 @@ static void pl2303_set_termios(struct tty_struct *tty, pl2303_vendor_write(0x0, 0x0, serial); } +out: kfree(buf); + kfree(buf_old); } static void pl2303_dtr_rts(struct usb_serial_port *port, int on) -- 1.7.10.4
>From d303ff67ab1b817bf75b32eaa276369039ee4af2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Sch=C3=A4fer?= <fschaefer.oss@xxxxxxxxxxxxxx> Date: Fri, 1 Nov 2013 13:59:58 +0100 Subject: [PATCH] EXPERIMENTAL PATCH 2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Frank Schäfer <fschaefer.oss@xxxxxxxxxxxxxx> --- drivers/usb/serial/pl2303.c | 29 ++++++++++++++++------------- 1 Datei geändert, 16 Zeilen hinzugefügt(+), 13 Zeilen entfernt(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index bedf8e4..b0d3d66 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -155,6 +155,7 @@ struct pl2303_private { spinlock_t lock; u8 line_control; u8 line_status; + u8 line_settings_enc[7]; /* baud rate, data bits, stop bits, parity */ }; static int pl2303_vendor_read(__u16 value, __u16 index, @@ -500,14 +501,6 @@ static void pl2303_set_termios(struct tty_struct *tty, int i; u8 control; - /* - * The PL2303 is reported to lose bytes if you change serial settings - * even to the same values as before. Thus we actually need to filter - * in this specific case. - */ - if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios)) - return; - buf = kzalloc(7, GFP_KERNEL); if (!buf) { dev_err(&port->dev, "%s - out of memory.\n", __func__); @@ -517,11 +510,6 @@ static void pl2303_set_termios(struct tty_struct *tty, return; } - i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, - 0, 0, buf, 7, 100); - dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); - if (C_CSIZE(tty)) { switch (C_CSIZE(tty)) { case CS5: @@ -591,10 +579,25 @@ static void pl2303_set_termios(struct tty_struct *tty, dev_dbg(&port->dev, "parity = none\n"); } + /* + * Some PL2303 chips are reported to lose bytes if you change the + * serial settings even to the same values as before. + * At least HXD chips are affected, HX chips seem to be ok. + * Thus we actually need to filter in this specific case. + * NOTE: a tty_termios_hw_change() check isn't sufficient, because + * different baud rates can result in identic encoded values. + */ + if (!memcmp(priv->line_settings_enc, buf, 7)) { + kfree(buf); + return; + } + i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, 0, 0, buf, 7, 100); dev_dbg(&port->dev, "0x21:0x20:0:0 %d\n", i); + if (i == 7) + memcpy(buf, priv->line_settings_enc, 7); /* change control lines if we are switching to or from B0 */ spin_lock_irqsave(&priv->lock, flags); -- 1.7.10.4