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/iuu_phoenix.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/iuu_phoenix.c')
-rw-r--r-- | drivers/usb/serial/iuu_phoenix.c | 43 |
1 files changed, 24 insertions, 19 deletions
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index a01e987c7d32..d65414888349 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c | |||
@@ -144,9 +144,10 @@ static void iuu_shutdown(struct usb_serial *serial) | |||
144 | } | 144 | } |
145 | } | 145 | } |
146 | 146 | ||
147 | static int iuu_tiocmset(struct usb_serial_port *port, struct file *file, | 147 | static int iuu_tiocmset(struct tty_struct *tty, struct file *file, |
148 | unsigned int set, unsigned int clear) | 148 | unsigned int set, unsigned int clear) |
149 | { | 149 | { |
150 | struct usb_serial_port *port = tty->driver_data; | ||
150 | struct iuu_private *priv = usb_get_serial_port_data(port); | 151 | struct iuu_private *priv = usb_get_serial_port_data(port); |
151 | unsigned long flags; | 152 | unsigned long flags; |
152 | 153 | ||
@@ -171,8 +172,9 @@ static int iuu_tiocmset(struct usb_serial_port *port, struct file *file, | |||
171 | * When no card , the reader respond with TIOCM_CD | 172 | * When no card , the reader respond with TIOCM_CD |
172 | * This is known as CD autodetect mechanism | 173 | * This is known as CD autodetect mechanism |
173 | */ | 174 | */ |
174 | static int iuu_tiocmget(struct usb_serial_port *port, struct file *file) | 175 | static int iuu_tiocmget(struct tty_struct *tty, struct file *file) |
175 | { | 176 | { |
177 | struct usb_serial_port *port = tty->driver_data; | ||
176 | struct iuu_private *priv = usb_get_serial_port_data(port); | 178 | struct iuu_private *priv = usb_get_serial_port_data(port); |
177 | unsigned long flags; | 179 | unsigned long flags; |
178 | int rc; | 180 | int rc; |
@@ -630,7 +632,7 @@ static void read_buf_callback(struct urb *urb) | |||
630 | } | 632 | } |
631 | 633 | ||
632 | dbg("%s - %i chars to write", __func__, urb->actual_length); | 634 | dbg("%s - %i chars to write", __func__, urb->actual_length); |
633 | tty = port->tty; | 635 | tty = port->port.tty; |
634 | if (data == NULL) | 636 | if (data == NULL) |
635 | dbg("%s - data is NULL !!!", __func__); | 637 | dbg("%s - data is NULL !!!", __func__); |
636 | if (tty && urb->actual_length && data) { | 638 | if (tty && urb->actual_length && data) { |
@@ -752,11 +754,10 @@ static void iuu_uart_read_callback(struct urb *urb) | |||
752 | /* if nothing to write call again rxcmd */ | 754 | /* if nothing to write call again rxcmd */ |
753 | dbg("%s - rxcmd recall", __func__); | 755 | dbg("%s - rxcmd recall", __func__); |
754 | iuu_led_activity_off(urb); | 756 | iuu_led_activity_off(urb); |
755 | return; | ||
756 | } | 757 | } |
757 | 758 | ||
758 | static int iuu_uart_write(struct usb_serial_port *port, const u8 *buf, | 759 | static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port, |
759 | int count) | 760 | const u8 *buf, int count) |
760 | { | 761 | { |
761 | struct iuu_private *priv = usb_get_serial_port_data(port); | 762 | struct iuu_private *priv = usb_get_serial_port_data(port); |
762 | unsigned long flags; | 763 | unsigned long flags; |
@@ -948,7 +949,8 @@ static int set_control_lines(struct usb_device *dev, u8 value) | |||
948 | return 0; | 949 | return 0; |
949 | } | 950 | } |
950 | 951 | ||
951 | static void iuu_close(struct usb_serial_port *port, struct file *filp) | 952 | static void iuu_close(struct tty_struct *tty, |
953 | struct usb_serial_port *port, struct file *filp) | ||
952 | { | 954 | { |
953 | /* iuu_led (port,255,0,0,0); */ | 955 | /* iuu_led (port,255,0,0,0); */ |
954 | struct usb_serial *serial; | 956 | struct usb_serial *serial; |
@@ -964,8 +966,8 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp) | |||
964 | 966 | ||
965 | iuu_uart_off(port); | 967 | iuu_uart_off(port); |
966 | if (serial->dev) { | 968 | if (serial->dev) { |
967 | if (port->tty) { | 969 | if (tty) { |
968 | c_cflag = port->tty->termios->c_cflag; | 970 | c_cflag = tty->termios->c_cflag; |
969 | if (c_cflag & HUPCL) { | 971 | if (c_cflag & HUPCL) { |
970 | /* drop DTR and RTS */ | 972 | /* drop DTR and RTS */ |
971 | priv = usb_get_serial_port_data(port); | 973 | priv = usb_get_serial_port_data(port); |
@@ -989,7 +991,8 @@ static void iuu_close(struct usb_serial_port *port, struct file *filp) | |||
989 | } | 991 | } |
990 | } | 992 | } |
991 | 993 | ||
992 | static int iuu_open(struct usb_serial_port *port, struct file *filp) | 994 | static int iuu_open(struct tty_struct *tty, |
995 | struct usb_serial_port *port, struct file *filp) | ||
993 | { | 996 | { |
994 | struct usb_serial *serial = port->serial; | 997 | struct usb_serial *serial = port->serial; |
995 | u8 *buf; | 998 | u8 *buf; |
@@ -1036,15 +1039,17 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp) | |||
1036 | 1039 | ||
1037 | /* set the termios structure */ | 1040 | /* set the termios structure */ |
1038 | spin_lock_irqsave(&priv->lock, flags); | 1041 | spin_lock_irqsave(&priv->lock, flags); |
1039 | if (!priv->termios_initialized) { | 1042 | if (tty && !priv->termios_initialized) { |
1040 | *(port->tty->termios) = tty_std_termios; | 1043 | *(tty->termios) = tty_std_termios; |
1041 | port->tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600 | 1044 | tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600 |
1042 | | TIOCM_CTS | CSTOPB | PARENB; | 1045 | | TIOCM_CTS | CSTOPB | PARENB; |
1043 | port->tty->termios->c_lflag = 0; | 1046 | tty->termios->c_ispeed = 9600; |
1044 | port->tty->termios->c_oflag = 0; | 1047 | tty->termios->c_ospeed = 9600; |
1045 | port->tty->termios->c_iflag = 0; | 1048 | tty->termios->c_lflag = 0; |
1049 | tty->termios->c_oflag = 0; | ||
1050 | tty->termios->c_iflag = 0; | ||
1046 | priv->termios_initialized = 1; | 1051 | priv->termios_initialized = 1; |
1047 | port->tty->low_latency = 1; | 1052 | tty->low_latency = 1; |
1048 | priv->poll = 0; | 1053 | priv->poll = 0; |
1049 | } | 1054 | } |
1050 | spin_unlock_irqrestore(&priv->lock, flags); | 1055 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -1148,7 +1153,7 @@ static int iuu_open(struct usb_serial_port *port, struct file *filp) | |||
1148 | if (result) { | 1153 | if (result) { |
1149 | dev_err(&port->dev, "%s - failed submitting read urb," | 1154 | dev_err(&port->dev, "%s - failed submitting read urb," |
1150 | " error %d\n", __func__, result); | 1155 | " error %d\n", __func__, result); |
1151 | iuu_close(port, NULL); | 1156 | iuu_close(tty, port, NULL); |
1152 | return -EPROTO; | 1157 | return -EPROTO; |
1153 | } else { | 1158 | } else { |
1154 | dbg("%s - rxcmd OK", __func__); | 1159 | dbg("%s - rxcmd OK", __func__); |