aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2008-01-08 09:55:51 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-01-08 19:16:34 -0500
commitbf5e5834bffc62b50cd4a201804506eb11ef1af8 (patch)
tree09cd94995a4c67b0fd84f7c81b7f2bb58fac8e50 /drivers
parentcf0594625083111ae522496dc1c256f7476939c2 (diff)
pl2303: Fix mode switching regression
Cleaning out all the incorrect 'no change made' checks for termios settings showed up a problem with the PL2303. The hardware here seems to lose sync and bits if you tell it to make no changes. This shows up with a real world application. To fix this the driver check for meaningful hardware changes is restored but doing the tests correctly and as a tty layer function so it doesn't get duplicated wrongly everywhere if other drivers turn out to need it. Signed-off-by: Alan Cox <alan@redhat.com> Tested-by: Mirko Parthey <mirko.parthey@informatik.tu-chemnitz.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/tty_ioctl.c19
-rw-r--r--drivers/usb/serial/pl2303.c7
2 files changed, 26 insertions, 0 deletions
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index e02d59245a17..d4b6d64e858b 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -365,6 +365,25 @@ void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old)
365EXPORT_SYMBOL(tty_termios_copy_hw); 365EXPORT_SYMBOL(tty_termios_copy_hw);
366 366
367/** 367/**
368 * tty_termios_hw_change - check for setting change
369 * @a: termios
370 * @b: termios to compare
371 *
372 * Check if any of the bits that affect a dumb device have changed
373 * between the two termios structures, or a speed change is needed.
374 */
375
376int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
377{
378 if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed)
379 return 1;
380 if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL))
381 return 1;
382 return 0;
383}
384EXPORT_SYMBOL(tty_termios_hw_change);
385
386/**
368 * change_termios - update termios values 387 * change_termios - update termios values
369 * @tty: tty to update 388 * @tty: tty to update
370 * @new_termios: desired new value 389 * @new_termios: desired new value
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index cf8add91de05..0da1df9c79bf 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -483,6 +483,13 @@ static void pl2303_set_termios(struct usb_serial_port *port,
483 } 483 }
484 spin_unlock_irqrestore(&priv->lock, flags); 484 spin_unlock_irqrestore(&priv->lock, flags);
485 485
486 /* The PL2303 is reported to lose bytes if you change
487 serial settings even to the same values as before. Thus
488 we actually need to filter in this specific case */
489
490 if (!tty_termios_hw_change(port->tty->termios, old_termios))
491 return;
492
486 cflag = port->tty->termios->c_cflag; 493 cflag = port->tty->termios->c_cflag;
487 494
488 buf = kzalloc(7, GFP_KERNEL); 495 buf = kzalloc(7, GFP_KERNEL);