diff options
author | Alan Cox <alan@redhat.com> | 2008-07-22 06:09:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-22 16:03:22 -0400 |
commit | 95da310e66ee8090119596c70ca8432e57f9a97f (patch) | |
tree | 7f18c30e9c9ad4d7d53df6453fa338be06f09a85 /drivers/usb/serial/ipaq.c | |
parent | 1aa3692da57c773e5c76de55c5c4a953962d360e (diff) |
usb_serial: API all change
USB serial likes to use port->tty back pointers for the real work it does and
to do so without any actual locking. Unfortunately when you consider hangup
events, hangup/parallel reopen or even worse hangup followed by parallel close
events the tty->port and port->tty pointers are not guaranteed to be the same
as port->tty is the active tty while tty->port is the port the tty may or
may not still be attached to.
So rework the entire API to pass the tty struct. For console cases we need
to pass both for now. This shows up multiple drivers that immediately crash
with USB console some of which have been fixed in the process.
Longer term we need a proper tty as console abstraction
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/usb/serial/ipaq.c')
-rw-r--r-- | drivers/usb/serial/ipaq.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 80d9ec5570d6..a7784642d6a1 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -74,19 +74,21 @@ static int connect_retries = KP_RETRIES; | |||
74 | static int initial_wait; | 74 | static int initial_wait; |
75 | 75 | ||
76 | /* Function prototypes for an ipaq */ | 76 | /* Function prototypes for an ipaq */ |
77 | static int ipaq_open (struct usb_serial_port *port, struct file *filp); | 77 | static int ipaq_open(struct tty_struct *tty, |
78 | static void ipaq_close (struct usb_serial_port *port, struct file *filp); | 78 | struct usb_serial_port *port, struct file *filp); |
79 | static int ipaq_startup (struct usb_serial *serial); | 79 | static void ipaq_close(struct tty_struct *tty, |
80 | static void ipaq_shutdown (struct usb_serial *serial); | 80 | struct usb_serial_port *port, struct file *filp); |
81 | static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf, | 81 | static int ipaq_startup(struct usb_serial *serial); |
82 | int count); | 82 | static void ipaq_shutdown(struct usb_serial *serial); |
83 | static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port, | ||
84 | const unsigned char *buf, int count); | ||
83 | static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf, | 85 | static int ipaq_write_bulk(struct usb_serial_port *port, const unsigned char *buf, |
84 | int count); | 86 | int count); |
85 | static void ipaq_write_gather(struct usb_serial_port *port); | 87 | static void ipaq_write_gather(struct usb_serial_port *port); |
86 | static void ipaq_read_bulk_callback (struct urb *urb); | 88 | static void ipaq_read_bulk_callback (struct urb *urb); |
87 | static void ipaq_write_bulk_callback(struct urb *urb); | 89 | static void ipaq_write_bulk_callback(struct urb *urb); |
88 | static int ipaq_write_room(struct usb_serial_port *port); | 90 | static int ipaq_write_room(struct tty_struct *tty); |
89 | static int ipaq_chars_in_buffer(struct usb_serial_port *port); | 91 | static int ipaq_chars_in_buffer(struct tty_struct *tty); |
90 | static void ipaq_destroy_lists(struct usb_serial_port *port); | 92 | static void ipaq_destroy_lists(struct usb_serial_port *port); |
91 | 93 | ||
92 | 94 | ||
@@ -591,7 +593,8 @@ static spinlock_t write_list_lock; | |||
591 | static int bytes_in; | 593 | static int bytes_in; |
592 | static int bytes_out; | 594 | static int bytes_out; |
593 | 595 | ||
594 | static int ipaq_open(struct usb_serial_port *port, struct file *filp) | 596 | static int ipaq_open(struct tty_struct *tty, |
597 | struct usb_serial_port *port, struct file *filp) | ||
595 | { | 598 | { |
596 | struct usb_serial *serial = port->serial; | 599 | struct usb_serial *serial = port->serial; |
597 | struct ipaq_private *priv; | 600 | struct ipaq_private *priv; |
@@ -637,10 +640,12 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp) | |||
637 | * discipline instead of queueing. | 640 | * discipline instead of queueing. |
638 | */ | 641 | */ |
639 | 642 | ||
640 | port->tty->low_latency = 1; | 643 | if (tty) { |
641 | port->tty->raw = 1; | 644 | tty->low_latency = 1; |
642 | port->tty->real_raw = 1; | 645 | /* FIXME: These two are bogus */ |
643 | 646 | tty->raw = 1; | |
647 | tty->real_raw = 1; | ||
648 | } | ||
644 | /* | 649 | /* |
645 | * Lose the small buffers usbserial provides. Make larger ones. | 650 | * Lose the small buffers usbserial provides. Make larger ones. |
646 | */ | 651 | */ |
@@ -714,7 +719,8 @@ error: | |||
714 | } | 719 | } |
715 | 720 | ||
716 | 721 | ||
717 | static void ipaq_close(struct usb_serial_port *port, struct file *filp) | 722 | static void ipaq_close(struct tty_struct *tty, |
723 | struct usb_serial_port *port, struct file *filp) | ||
718 | { | 724 | { |
719 | struct ipaq_private *priv = usb_get_serial_port_data(port); | 725 | struct ipaq_private *priv = usb_get_serial_port_data(port); |
720 | 726 | ||
@@ -751,7 +757,7 @@ static void ipaq_read_bulk_callback(struct urb *urb) | |||
751 | 757 | ||
752 | usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); | 758 | usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); |
753 | 759 | ||
754 | tty = port->tty; | 760 | tty = port->port.tty; |
755 | if (tty && urb->actual_length) { | 761 | if (tty && urb->actual_length) { |
756 | tty_buffer_request_room(tty, urb->actual_length); | 762 | tty_buffer_request_room(tty, urb->actual_length); |
757 | tty_insert_flip_string(tty, data, urb->actual_length); | 763 | tty_insert_flip_string(tty, data, urb->actual_length); |
@@ -770,8 +776,8 @@ static void ipaq_read_bulk_callback(struct urb *urb) | |||
770 | return; | 776 | return; |
771 | } | 777 | } |
772 | 778 | ||
773 | static int ipaq_write(struct usb_serial_port *port, const unsigned char *buf, | 779 | static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port, |
774 | int count) | 780 | const unsigned char *buf, int count) |
775 | { | 781 | { |
776 | const unsigned char *current_position = buf; | 782 | const unsigned char *current_position = buf; |
777 | int bytes_sent = 0; | 783 | int bytes_sent = 0; |
@@ -905,16 +911,18 @@ static void ipaq_write_bulk_callback(struct urb *urb) | |||
905 | usb_serial_port_softint(port); | 911 | usb_serial_port_softint(port); |
906 | } | 912 | } |
907 | 913 | ||
908 | static int ipaq_write_room(struct usb_serial_port *port) | 914 | static int ipaq_write_room(struct tty_struct *tty) |
909 | { | 915 | { |
916 | struct usb_serial_port *port = tty->driver_data; | ||
910 | struct ipaq_private *priv = usb_get_serial_port_data(port); | 917 | struct ipaq_private *priv = usb_get_serial_port_data(port); |
911 | 918 | ||
912 | dbg("%s - freelen %d", __func__, priv->free_len); | 919 | dbg("%s - freelen %d", __func__, priv->free_len); |
913 | return priv->free_len; | 920 | return priv->free_len; |
914 | } | 921 | } |
915 | 922 | ||
916 | static int ipaq_chars_in_buffer(struct usb_serial_port *port) | 923 | static int ipaq_chars_in_buffer(struct tty_struct *tty) |
917 | { | 924 | { |
925 | struct usb_serial_port *port = tty->driver_data; | ||
918 | struct ipaq_private *priv = usb_get_serial_port_data(port); | 926 | struct ipaq_private *priv = usb_get_serial_port_data(port); |
919 | 927 | ||
920 | dbg("%s - queuelen %d", __func__, priv->queue_len); | 928 | dbg("%s - queuelen %d", __func__, priv->queue_len); |