diff options
author | Sarah Sharp <saharabeara@gmail.com> | 2007-12-14 17:08:35 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-02-01 17:34:55 -0500 |
commit | 3e152505a57db6622deb1322c22551c046e33d16 (patch) | |
tree | c6fd97a1a5a882e41e30c6e97efe6ca1182fe13e /drivers/usb | |
parent | eb44da0b3aa0105cb38d81c5747a8feae64834be (diff) |
USB: pl2303: Move pl2303 vendor specific init to probe function.
Without this fix, the pl2303 usb-serial adapter would not suspend properly
unless it had been opened first. A pl2303 type_1 chip will still break if the
system is hibernated while the RS-232 connector is powered by another system.
This was broken before, and a reset resume does not fix it. All other suspend
and autosuspend scenarios work with ATEN pl2303 adaptors with HX and type_1 chips.
Signed-off-by: Sarah Sharp <saharabeara@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/pl2303.c | 49 |
1 files changed, 24 insertions, 25 deletions
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index fd8c09fd3288..c27f2f822f13 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -338,8 +338,13 @@ static int pl2303_startup(struct usb_serial *serial) | |||
338 | { | 338 | { |
339 | struct pl2303_private *priv; | 339 | struct pl2303_private *priv; |
340 | enum pl2303_type type = type_0; | 340 | enum pl2303_type type = type_0; |
341 | unsigned char *buf; | ||
341 | int i; | 342 | int i; |
342 | 343 | ||
344 | buf = kmalloc(10, GFP_KERNEL); | ||
345 | if (buf == NULL) | ||
346 | return -ENOMEM; | ||
347 | |||
343 | if (serial->dev->descriptor.bDeviceClass == 0x02) | 348 | if (serial->dev->descriptor.bDeviceClass == 0x02) |
344 | type = type_0; | 349 | type = type_0; |
345 | else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) | 350 | else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40) |
@@ -364,9 +369,27 @@ static int pl2303_startup(struct usb_serial *serial) | |||
364 | priv->type = type; | 369 | priv->type = type; |
365 | usb_set_serial_port_data(serial->port[i], priv); | 370 | usb_set_serial_port_data(serial->port[i], priv); |
366 | } | 371 | } |
372 | |||
373 | pl2303_vendor_read(0x8484, 0, serial, buf); | ||
374 | pl2303_vendor_write(0x0404, 0, serial); | ||
375 | pl2303_vendor_read(0x8484, 0, serial, buf); | ||
376 | pl2303_vendor_read(0x8383, 0, serial, buf); | ||
377 | pl2303_vendor_read(0x8484, 0, serial, buf); | ||
378 | pl2303_vendor_write(0x0404, 1, serial); | ||
379 | pl2303_vendor_read(0x8484, 0, serial, buf); | ||
380 | pl2303_vendor_read(0x8383, 0, serial, buf); | ||
381 | pl2303_vendor_write(0, 1, serial); | ||
382 | pl2303_vendor_write(1, 0, serial); | ||
383 | if (type == HX) | ||
384 | pl2303_vendor_write(2, 0x44, serial); | ||
385 | else | ||
386 | pl2303_vendor_write(2, 0x24, serial); | ||
387 | |||
388 | kfree(buf); | ||
367 | return 0; | 389 | return 0; |
368 | 390 | ||
369 | cleanup: | 391 | cleanup: |
392 | kfree(buf); | ||
370 | for (--i; i>=0; --i) { | 393 | for (--i; i>=0; --i) { |
371 | priv = usb_get_serial_port_data(serial->port[i]); | 394 | priv = usb_get_serial_port_data(serial->port[i]); |
372 | pl2303_buf_free(priv->buf); | 395 | pl2303_buf_free(priv->buf); |
@@ -690,7 +713,6 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp) | |||
690 | struct ktermios tmp_termios; | 713 | struct ktermios tmp_termios; |
691 | struct usb_serial *serial = port->serial; | 714 | struct usb_serial *serial = port->serial; |
692 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 715 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
693 | unsigned char *buf; | ||
694 | int result; | 716 | int result; |
695 | 717 | ||
696 | dbg("%s - port %d", __FUNCTION__, port->number); | 718 | dbg("%s - port %d", __FUNCTION__, port->number); |
@@ -698,35 +720,12 @@ static int pl2303_open(struct usb_serial_port *port, struct file *filp) | |||
698 | if (priv->type != HX) { | 720 | if (priv->type != HX) { |
699 | usb_clear_halt(serial->dev, port->write_urb->pipe); | 721 | usb_clear_halt(serial->dev, port->write_urb->pipe); |
700 | usb_clear_halt(serial->dev, port->read_urb->pipe); | 722 | usb_clear_halt(serial->dev, port->read_urb->pipe); |
701 | } | 723 | } else { |
702 | |||
703 | buf = kmalloc(10, GFP_KERNEL); | ||
704 | if (buf==NULL) | ||
705 | return -ENOMEM; | ||
706 | |||
707 | pl2303_vendor_read(0x8484, 0, serial, buf); | ||
708 | pl2303_vendor_write(0x0404, 0, serial); | ||
709 | pl2303_vendor_read(0x8484, 0, serial, buf); | ||
710 | pl2303_vendor_read(0x8383, 0, serial, buf); | ||
711 | pl2303_vendor_read(0x8484, 0, serial, buf); | ||
712 | pl2303_vendor_write(0x0404, 1, serial); | ||
713 | pl2303_vendor_read(0x8484, 0, serial, buf); | ||
714 | pl2303_vendor_read(0x8383, 0, serial, buf); | ||
715 | pl2303_vendor_write(0, 1, serial); | ||
716 | pl2303_vendor_write(1, 0, serial); | ||
717 | |||
718 | if (priv->type == HX) { | ||
719 | /* HX chip */ | ||
720 | pl2303_vendor_write(2, 0x44, serial); | ||
721 | /* reset upstream data pipes */ | 724 | /* reset upstream data pipes */ |
722 | pl2303_vendor_write(8, 0, serial); | 725 | pl2303_vendor_write(8, 0, serial); |
723 | pl2303_vendor_write(9, 0, serial); | 726 | pl2303_vendor_write(9, 0, serial); |
724 | } else { | ||
725 | pl2303_vendor_write(2, 0x24, serial); | ||
726 | } | 727 | } |
727 | 728 | ||
728 | kfree(buf); | ||
729 | |||
730 | /* Setup termios */ | 729 | /* Setup termios */ |
731 | if (port->tty) { | 730 | if (port->tty) { |
732 | pl2303_set_termios(port, &tmp_termios); | 731 | pl2303_set_termios(port, &tmp_termios); |