diff options
author | Ming Lei <tom.leiming@gmail.com> | 2009-02-20 08:23:09 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-03-24 19:20:36 -0400 |
commit | 1ded7ea47b8829a06068c3bb5e3ebe471076617a (patch) | |
tree | 113e3daefadaec5e25c7b4b8a7ce3cff23ba0327 /drivers/usb | |
parent | a227fd7db74fa05d866790a4b29ba049bb5035cc (diff) |
USB: ch341 serial: fix port number changed after resume
This patch fixes the following bug:
.plug ch341 usb serial port into a hub port;
.ch341 driver bound to the device and /dev/ttyUSB0 comes
.open /dev/ttyUSB0 by minicom and we can use the serial successfully
.suspend the ch341 usb serial device(such as: echo suspend > power/level)
.resume the ch341 usb serial device (such as: echo on > power/level)
.new port /dev/ttyUSB1 comes ,and the original /dev/ttyUSB0 still exists,
but is no longer usable by minicom
The patch adds suspend and resume callback to ch341 usb driver to prevent it
from unbinding during suspend. The /dev/ttyUSB0 is not released until being
closed, so /dev/ttyUSB1 comes after resume, and the original /dev/ttyUSB0 is
no longer usable by minicom. It is really a mess for a minicom user.
This patch also adds the reset_resume callback to make it usable after resuming
from STR or hibernation, for generally STR or hibernation will make the vbus
of root-hub lost.
Finally enable the driver's supports_autosuspend, for the device is in working
order with it.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/ch341.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index d5ea679e1698..ab4cc277aa65 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c | |||
@@ -529,12 +529,34 @@ static int ch341_tiocmget(struct tty_struct *tty, struct file *file) | |||
529 | return result; | 529 | return result; |
530 | } | 530 | } |
531 | 531 | ||
532 | |||
533 | static int ch341_reset_resume(struct usb_interface *intf) | ||
534 | { | ||
535 | struct usb_device *dev = interface_to_usbdev(intf); | ||
536 | struct usb_serial *serial = NULL; | ||
537 | struct ch341_private *priv; | ||
538 | |||
539 | serial = usb_get_intfdata(intf); | ||
540 | priv = usb_get_serial_port_data(serial->port[0]); | ||
541 | |||
542 | /*reconfigure ch341 serial port after bus-reset*/ | ||
543 | ch341_configure(dev, priv); | ||
544 | |||
545 | usb_serial_resume(intf); | ||
546 | |||
547 | return 0; | ||
548 | } | ||
549 | |||
532 | static struct usb_driver ch341_driver = { | 550 | static struct usb_driver ch341_driver = { |
533 | .name = "ch341", | 551 | .name = "ch341", |
534 | .probe = usb_serial_probe, | 552 | .probe = usb_serial_probe, |
535 | .disconnect = usb_serial_disconnect, | 553 | .disconnect = usb_serial_disconnect, |
554 | .suspend = usb_serial_suspend, | ||
555 | .resume = usb_serial_resume, | ||
556 | .reset_resume = ch341_reset_resume, | ||
536 | .id_table = id_table, | 557 | .id_table = id_table, |
537 | .no_dynamic_id = 1, | 558 | .no_dynamic_id = 1, |
559 | .supports_autosuspend = 1, | ||
538 | }; | 560 | }; |
539 | 561 | ||
540 | static struct usb_serial_driver ch341_device = { | 562 | static struct usb_serial_driver ch341_device = { |