[RFC/RFT PATCH] pl2303: avoid data corruption with some chip types

2013-11-01 Thread Frank Schäfer
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.

Signed-off-by: Frank Schäfer fschaefer@googlemail.com
Cc: sta...@kernel.org
---
 drivers/usb/serial/pl2303.c |   22 ++
 1 Datei geändert, 14 Zeilen hinzugefügt(+), 8 Zeilen entfernt(-)

diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index bedf8e4..27a2691 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__);
@@ -591,10 +584,23 @@ 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))
+   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

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC/RFT PATCH] pl2303: avoid data corruption with some chip types

2013-11-01 Thread 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).
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC/RFT PATCH] pl2303: avoid data corruption with some chip types

2013-11-01 Thread Frank Schäfer
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@googlemail.com
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@googlemail.com
---
 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@googlemail.com
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@googlemail.com
---
 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 

Re: [RFC/RFT PATCH] pl2303: avoid data corruption with some chip types

2013-11-01 Thread Johan Hovold
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.

We're gonna need something along these lines, but this is just a hack
that not even correct.

 Signed-off-by: Frank Schäfer fschaefer@googlemail.com
 Cc: sta...@kernel.org
 ---
  drivers/usb/serial/pl2303.c |   22 ++
  1 Datei geändert, 14 Zeilen hinzugefügt(+), 8 Zeilen entfernt(-)
 
 diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
 index bedf8e4..27a2691 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__);

Here another call to get the line settings is made. Have you verified
that that isn't related to the lost bytes?


 @@ -591,10 +584,23 @@ 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))
 + return;
 +

Here you're returning if there no baud rate change, which means that
flow control is never handled a bit further down in set_termios.

   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

Again, this too much of a hack. There is a long-standing bug that needs
to be addressed. Let's think some more of how best to handle that (and
get to the bottom with exactly what requests are causing it, etc).

The important thing is to fix the regression. We can fix this bug during
the 3.13-cycle if the fix is not too invasive.

Sorry,
Johan
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html